472 #if defined(_MSC_VER) && !defined(__clang__)
473 #pragma warning(push)
474 #pragma warning(disable:4201)
475 #pragma warning(disable:4324)
477 #pragma GCC diagnostic push
478 #pragma GCC diagnostic ignored "-Wpedantic"
479 #if defined(__clang__)
480 #pragma GCC diagnostic ignored "-Wc11-extensions"
487 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
490 #define MA_WIN32_DESKTOP
498 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
511 #ifdef __EMSCRIPTEN__
512 #define MA_EMSCRIPTEN
520 #if defined(__clang__)
521 #pragma GCC diagnostic push
522 #pragma GCC diagnostic ignored "-Wlanguage-extension-token"
523 #pragma GCC diagnostic ignored "-Wlong-long"
524 #pragma GCC diagnostic ignored "-Wc++11-long-long"
534 #if defined(__clang__)
535 #pragma GCC diagnostic pop
538 #define MA_HAS_STDINT
559 #elif defined(__GNUC__)
560 #if defined(__LP64__)
579 #if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
588 #if defined(SIZE_MAX)
589 #define MA_SIZE_MAX SIZE_MAX
591 #define MA_SIZE_MAX 0xFFFFFFFF
596 #define MA_INLINE __forceinline
597 #elif defined(__GNUC__)
605 #if defined(__STRICT_ANSI__)
606 #define MA_INLINE __inline__ __attribute__((always_inline))
608 #define MA_INLINE inline __attribute__((always_inline))
614 #if defined(_MSC_VER)
616 #define MA_ALIGN(alignment) __declspec(align(alignment))
618 #elif !defined(__DMC__)
619 #define MA_ALIGN(alignment) __attribute__((aligned(alignment)))
622 #define MA_ALIGN(alignment)
626 #define MA_ALIGNED_STRUCT(alignment) MA_ALIGN(alignment) struct
628 #define MA_ALIGNED_STRUCT(alignment) struct MA_ALIGN(alignment)
632 #define MA_SIMD_ALIGNMENT 64
636 #define MA_LOG_LEVEL_VERBOSE 4
637 #define MA_LOG_LEVEL_INFO 3
638 #define MA_LOG_LEVEL_WARNING 2
639 #define MA_LOG_LEVEL_ERROR 1
642 #define MA_LOG_LEVEL MA_LOG_LEVEL_ERROR
649 #define MA_CHANNEL_NONE 0
650 #define MA_CHANNEL_MONO 1
651 #define MA_CHANNEL_FRONT_LEFT 2
652 #define MA_CHANNEL_FRONT_RIGHT 3
653 #define MA_CHANNEL_FRONT_CENTER 4
654 #define MA_CHANNEL_LFE 5
655 #define MA_CHANNEL_BACK_LEFT 6
656 #define MA_CHANNEL_BACK_RIGHT 7
657 #define MA_CHANNEL_FRONT_LEFT_CENTER 8
658 #define MA_CHANNEL_FRONT_RIGHT_CENTER 9
659 #define MA_CHANNEL_BACK_CENTER 10
660 #define MA_CHANNEL_SIDE_LEFT 11
661 #define MA_CHANNEL_SIDE_RIGHT 12
662 #define MA_CHANNEL_TOP_CENTER 13
663 #define MA_CHANNEL_TOP_FRONT_LEFT 14
664 #define MA_CHANNEL_TOP_FRONT_CENTER 15
665 #define MA_CHANNEL_TOP_FRONT_RIGHT 16
666 #define MA_CHANNEL_TOP_BACK_LEFT 17
667 #define MA_CHANNEL_TOP_BACK_CENTER 18
668 #define MA_CHANNEL_TOP_BACK_RIGHT 19
669 #define MA_CHANNEL_AUX_0 20
670 #define MA_CHANNEL_AUX_1 21
671 #define MA_CHANNEL_AUX_2 22
672 #define MA_CHANNEL_AUX_3 23
673 #define MA_CHANNEL_AUX_4 24
674 #define MA_CHANNEL_AUX_5 25
675 #define MA_CHANNEL_AUX_6 26
676 #define MA_CHANNEL_AUX_7 27
677 #define MA_CHANNEL_AUX_8 28
678 #define MA_CHANNEL_AUX_9 29
679 #define MA_CHANNEL_AUX_10 30
680 #define MA_CHANNEL_AUX_11 31
681 #define MA_CHANNEL_AUX_12 32
682 #define MA_CHANNEL_AUX_13 33
683 #define MA_CHANNEL_AUX_14 34
684 #define MA_CHANNEL_AUX_15 35
685 #define MA_CHANNEL_AUX_16 36
686 #define MA_CHANNEL_AUX_17 37
687 #define MA_CHANNEL_AUX_18 38
688 #define MA_CHANNEL_AUX_19 39
689 #define MA_CHANNEL_AUX_20 40
690 #define MA_CHANNEL_AUX_21 41
691 #define MA_CHANNEL_AUX_22 42
692 #define MA_CHANNEL_AUX_23 43
693 #define MA_CHANNEL_AUX_24 44
694 #define MA_CHANNEL_AUX_25 45
695 #define MA_CHANNEL_AUX_26 46
696 #define MA_CHANNEL_AUX_27 47
697 #define MA_CHANNEL_AUX_28 48
698 #define MA_CHANNEL_AUX_29 49
699 #define MA_CHANNEL_AUX_30 50
700 #define MA_CHANNEL_AUX_31 51
701 #define MA_CHANNEL_LEFT MA_CHANNEL_FRONT_LEFT
702 #define MA_CHANNEL_RIGHT MA_CHANNEL_FRONT_RIGHT
703 #define MA_CHANNEL_POSITION_COUNT MA_CHANNEL_AUX_31 + 1
711 #define MA_INVALID_ARGS -2
712 #define MA_INVALID_OPERATION -3
713 #define MA_OUT_OF_MEMORY -4
714 #define MA_ACCESS_DENIED -5
715 #define MA_TOO_LARGE -6
716 #define MA_TIMEOUT -7
719 #define MA_FORMAT_NOT_SUPPORTED -100
720 #define MA_DEVICE_TYPE_NOT_SUPPORTED -101
721 #define MA_SHARE_MODE_NOT_SUPPORTED -102
722 #define MA_NO_BACKEND -103
723 #define MA_NO_DEVICE -104
724 #define MA_API_NOT_FOUND -105
725 #define MA_INVALID_DEVICE_CONFIG -106
728 #define MA_DEVICE_BUSY -200
729 #define MA_DEVICE_NOT_INITIALIZED -201
730 #define MA_DEVICE_NOT_STARTED -202
731 #define MA_DEVICE_UNAVAILABLE -203
734 #define MA_FAILED_TO_MAP_DEVICE_BUFFER -300
735 #define MA_FAILED_TO_UNMAP_DEVICE_BUFFER -301
736 #define MA_FAILED_TO_INIT_BACKEND -302
737 #define MA_FAILED_TO_READ_DATA_FROM_CLIENT -303
738 #define MA_FAILED_TO_READ_DATA_FROM_DEVICE -304
739 #define MA_FAILED_TO_SEND_DATA_TO_CLIENT -305
740 #define MA_FAILED_TO_SEND_DATA_TO_DEVICE -306
741 #define MA_FAILED_TO_OPEN_BACKEND_DEVICE -307
742 #define MA_FAILED_TO_START_BACKEND_DEVICE -308
743 #define MA_FAILED_TO_STOP_BACKEND_DEVICE -309
744 #define MA_FAILED_TO_CONFIGURE_BACKEND_DEVICE -310
745 #define MA_FAILED_TO_CREATE_MUTEX -311
746 #define MA_FAILED_TO_CREATE_EVENT -312
747 #define MA_FAILED_TO_CREATE_THREAD -313
751 #define MA_SAMPLE_RATE_8000 8000
752 #define MA_SAMPLE_RATE_11025 11025
753 #define MA_SAMPLE_RATE_16000 16000
754 #define MA_SAMPLE_RATE_22050 22050
755 #define MA_SAMPLE_RATE_24000 24000
756 #define MA_SAMPLE_RATE_32000 32000
757 #define MA_SAMPLE_RATE_44100 44100
758 #define MA_SAMPLE_RATE_48000 48000
759 #define MA_SAMPLE_RATE_88200 88200
760 #define MA_SAMPLE_RATE_96000 96000
761 #define MA_SAMPLE_RATE_176400 176400
762 #define MA_SAMPLE_RATE_192000 192000
763 #define MA_SAMPLE_RATE_352800 352800
764 #define MA_SAMPLE_RATE_384000 384000
766 #define MA_MIN_PCM_SAMPLE_SIZE_IN_BYTES 1
767 #define MA_MAX_PCM_SAMPLE_SIZE_IN_BYTES 8
768 #define MA_MIN_CHANNELS 1
769 #define MA_MAX_CHANNELS 32
770 #define MA_MIN_SAMPLE_RATE MA_SAMPLE_RATE_8000
771 #define MA_MAX_SAMPLE_RATE MA_SAMPLE_RATE_384000
772 #define MA_SRC_SINC_MIN_WINDOW_WIDTH 2
773 #define MA_SRC_SINC_MAX_WINDOW_WIDTH 32
774 #define MA_SRC_SINC_DEFAULT_WINDOW_WIDTH 32
775 #define MA_SRC_SINC_LOOKUP_TABLE_RESOLUTION 8
776 #define MA_SRC_INPUT_BUFFER_SIZE_IN_SAMPLES 256
1017 ma_bool32 isDynamicSampleRateAllowed : 1;
1018 ma_bool32 isPreFormatConversionRequired : 1;
1019 ma_bool32 isPostFormatConversionRequired : 1;
1381 ma_uint64 ma_convert_frames_ex(
void* pOut,
ma_format formatOut,
ma_uint32 channelsOut,
ma_uint32 sampleRateOut,
ma_channel channelMapOut[
MA_MAX_CHANNELS],
const void* pIn,
ma_format formatIn,
ma_uint32 channelsIn,
ma_uint32 sampleRateIn,
ma_channel channelMapIn[
MA_MAX_CHANNELS],
ma_uint64 frameCount);
1450 ma_result ma_rb_init_ex(
size_t subbufferSizeInBytes,
size_t subbufferCount,
size_t subbufferStrideInBytes,
void* pOptionalPreallocatedBuffer,
ma_rb* pRB);
1601 #ifndef MA_NO_DEVICE_IO
1603 #if defined(MA_WIN32)
1604 #define MA_SUPPORT_WASAPI
1605 #if defined(MA_WIN32_DESKTOP)
1606 #define MA_SUPPORT_DSOUND
1607 #define MA_SUPPORT_WINMM
1608 #define MA_SUPPORT_JACK
1611 #if defined(MA_UNIX)
1612 #if defined(MA_LINUX)
1613 #if !defined(MA_ANDROID)
1614 #define MA_SUPPORT_ALSA
1617 #if !defined(MA_BSD) && !defined(MA_ANDROID) && !defined(MA_EMSCRIPTEN)
1618 #define MA_SUPPORT_PULSEAUDIO
1619 #define MA_SUPPORT_JACK
1621 #if defined(MA_ANDROID)
1622 #define MA_SUPPORT_AAUDIO
1623 #define MA_SUPPORT_OPENSL
1625 #if defined(__OpenBSD__)
1626 #define MA_SUPPORT_SNDIO
1628 #if defined(__NetBSD__) || defined(__OpenBSD__)
1629 #define MA_SUPPORT_AUDIO4
1631 #if defined(__FreeBSD__) || defined(__DragonFly__)
1632 #define MA_SUPPORT_OSS
1635 #if defined(MA_APPLE)
1636 #define MA_SUPPORT_COREAUDIO
1638 #if defined(MA_EMSCRIPTEN)
1639 #define MA_SUPPORT_WEBAUDIO
1643 #if !defined(MA_EMSCRIPTEN)
1644 #define MA_SUPPORT_NULL
1648 #if !defined(MA_NO_WASAPI) && defined(MA_SUPPORT_WASAPI)
1649 #define MA_ENABLE_WASAPI
1651 #if !defined(MA_NO_DSOUND) && defined(MA_SUPPORT_DSOUND)
1652 #define MA_ENABLE_DSOUND
1654 #if !defined(MA_NO_WINMM) && defined(MA_SUPPORT_WINMM)
1655 #define MA_ENABLE_WINMM
1657 #if !defined(MA_NO_ALSA) && defined(MA_SUPPORT_ALSA)
1658 #define MA_ENABLE_ALSA
1660 #if !defined(MA_NO_PULSEAUDIO) && defined(MA_SUPPORT_PULSEAUDIO)
1661 #define MA_ENABLE_PULSEAUDIO
1663 #if !defined(MA_NO_JACK) && defined(MA_SUPPORT_JACK)
1664 #define MA_ENABLE_JACK
1666 #if !defined(MA_NO_COREAUDIO) && defined(MA_SUPPORT_COREAUDIO)
1667 #define MA_ENABLE_COREAUDIO
1669 #if !defined(MA_NO_SNDIO) && defined(MA_SUPPORT_SNDIO)
1670 #define MA_ENABLE_SNDIO
1672 #if !defined(MA_NO_AUDIO4) && defined(MA_SUPPORT_AUDIO4)
1673 #define MA_ENABLE_AUDIO4
1675 #if !defined(MA_NO_OSS) && defined(MA_SUPPORT_OSS)
1676 #define MA_ENABLE_OSS
1678 #if !defined(MA_NO_AAUDIO) && defined(MA_SUPPORT_AAUDIO)
1679 #define MA_ENABLE_AAUDIO
1681 #if !defined(MA_NO_OPENSL) && defined(MA_SUPPORT_OPENSL)
1682 #define MA_ENABLE_OPENSL
1684 #if !defined(MA_NO_WEBAUDIO) && defined(MA_SUPPORT_WEBAUDIO)
1685 #define MA_ENABLE_WEBAUDIO
1687 #if !defined(MA_NO_NULL) && defined(MA_SUPPORT_NULL)
1688 #define MA_ENABLE_NULL
1691 #ifdef MA_SUPPORT_WASAPI
1698 } ma_IMMNotificationClient;
1861 #ifdef MA_SUPPORT_WASAPI
1864 #ifdef MA_SUPPORT_DSOUND
1867 #ifdef MA_SUPPORT_WINMM
1870 #ifdef MA_SUPPORT_ALSA
1873 #ifdef MA_SUPPORT_PULSEAUDIO
1876 #ifdef MA_SUPPORT_JACK
1879 #ifdef MA_SUPPORT_COREAUDIO
1880 char coreaudio[256];
1882 #ifdef MA_SUPPORT_SNDIO
1885 #ifdef MA_SUPPORT_AUDIO4
1888 #ifdef MA_SUPPORT_OSS
1891 #ifdef MA_SUPPORT_AAUDIO
1894 #ifdef MA_SUPPORT_OPENSL
1897 #ifdef MA_SUPPORT_WEBAUDIO
1900 #ifdef MA_SUPPORT_NULL
2030 #ifdef MA_SUPPORT_WASAPI
2036 #ifdef MA_SUPPORT_DSOUND
2041 ma_proc DirectSoundEnumerateA;
2042 ma_proc DirectSoundCaptureCreate;
2043 ma_proc DirectSoundCaptureEnumerateA;
2046 #ifdef MA_SUPPORT_WINMM
2055 ma_proc waveOutUnprepareHeader;
2063 ma_proc waveInUnprepareHeader;
2069 #ifdef MA_SUPPORT_ALSA
2075 ma_proc snd_pcm_hw_params_sizeof;
2076 ma_proc snd_pcm_hw_params_any;
2077 ma_proc snd_pcm_hw_params_set_format;
2078 ma_proc snd_pcm_hw_params_set_format_first;
2079 ma_proc snd_pcm_hw_params_get_format_mask;
2080 ma_proc snd_pcm_hw_params_set_channels_near;
2081 ma_proc snd_pcm_hw_params_set_rate_resample;
2082 ma_proc snd_pcm_hw_params_set_rate_near;
2083 ma_proc snd_pcm_hw_params_set_buffer_size_near;
2084 ma_proc snd_pcm_hw_params_set_periods_near;
2085 ma_proc snd_pcm_hw_params_set_access;
2086 ma_proc snd_pcm_hw_params_get_format;
2087 ma_proc snd_pcm_hw_params_get_channels;
2088 ma_proc snd_pcm_hw_params_get_channels_min;
2089 ma_proc snd_pcm_hw_params_get_channels_max;
2090 ma_proc snd_pcm_hw_params_get_rate;
2091 ma_proc snd_pcm_hw_params_get_rate_min;
2092 ma_proc snd_pcm_hw_params_get_rate_max;
2093 ma_proc snd_pcm_hw_params_get_buffer_size;
2094 ma_proc snd_pcm_hw_params_get_periods;
2095 ma_proc snd_pcm_hw_params_get_access;
2097 ma_proc snd_pcm_sw_params_sizeof;
2098 ma_proc snd_pcm_sw_params_current;
2099 ma_proc snd_pcm_sw_params_get_boundary;
2100 ma_proc snd_pcm_sw_params_set_avail_min;
2101 ma_proc snd_pcm_sw_params_set_start_threshold;
2102 ma_proc snd_pcm_sw_params_set_stop_threshold;
2104 ma_proc snd_pcm_format_mask_sizeof;
2105 ma_proc snd_pcm_format_mask_test;
2113 ma_proc snd_device_name_get_hint;
2115 ma_proc snd_device_name_free_hint;
2126 ma_proc snd_pcm_info_get_name;
2127 ma_proc snd_config_update_free_global;
2133 #ifdef MA_SUPPORT_PULSEAUDIO
2145 ma_proc pa_context_disconnect;
2146 ma_proc pa_context_set_state_callback;
2148 ma_proc pa_context_get_sink_info_list;
2149 ma_proc pa_context_get_source_info_list;
2150 ma_proc pa_context_get_sink_info_by_name;
2151 ma_proc pa_context_get_source_info_by_name;
2153 ma_proc pa_operation_get_state;
2154 ma_proc pa_channel_map_init_extend;
2156 ma_proc pa_channel_map_compatible;
2159 ma_proc pa_stream_connect_playback;
2160 ma_proc pa_stream_connect_record;
2163 ma_proc pa_stream_get_sample_spec;
2164 ma_proc pa_stream_get_channel_map;
2165 ma_proc pa_stream_get_buffer_attr;
2166 ma_proc pa_stream_set_buffer_attr;
2167 ma_proc pa_stream_get_device_name;
2168 ma_proc pa_stream_set_write_callback;
2169 ma_proc pa_stream_set_read_callback;
2175 ma_proc pa_stream_begin_write;
2179 ma_proc pa_stream_writable_size;
2180 ma_proc pa_stream_readable_size;
2182 char* pApplicationName;
2187 #ifdef MA_SUPPORT_JACK
2193 ma_proc jack_client_name_size;
2194 ma_proc jack_set_process_callback;
2195 ma_proc jack_set_buffer_size_callback;
2212 #ifdef MA_SUPPORT_COREAUDIO
2220 ma_proc AudioObjectGetPropertyData;
2221 ma_proc AudioObjectGetPropertyDataSize;
2222 ma_proc AudioObjectSetPropertyData;
2223 ma_proc AudioObjectAddPropertyListener;
2224 ma_proc AudioObjectRemovePropertyListener;
2227 ma_proc AudioComponentFindNext;
2228 ma_proc AudioComponentInstanceDispose;
2229 ma_proc AudioComponentInstanceNew;
2232 ma_proc AudioUnitAddPropertyListener;
2233 ma_proc AudioUnitGetPropertyInfo;
2242 #ifdef MA_SUPPORT_SNDIO
2265 #ifdef MA_SUPPORT_AUDIO4
2271 #ifdef MA_SUPPORT_OSS
2278 #ifdef MA_SUPPORT_AAUDIO
2282 ma_proc AAudio_createStreamBuilder;
2283 ma_proc AAudioStreamBuilder_delete;
2284 ma_proc AAudioStreamBuilder_setDeviceId;
2285 ma_proc AAudioStreamBuilder_setDirection;
2286 ma_proc AAudioStreamBuilder_setSharingMode;
2287 ma_proc AAudioStreamBuilder_setFormat;
2288 ma_proc AAudioStreamBuilder_setChannelCount;
2289 ma_proc AAudioStreamBuilder_setSampleRate;
2290 ma_proc AAudioStreamBuilder_setBufferCapacityInFrames;
2291 ma_proc AAudioStreamBuilder_setFramesPerDataCallback;
2292 ma_proc AAudioStreamBuilder_setDataCallback;
2293 ma_proc AAudioStreamBuilder_setPerformanceMode;
2294 ma_proc AAudioStreamBuilder_openStream;
2296 ma_proc AAudioStream_getState;
2297 ma_proc AAudioStream_waitForStateChange;
2298 ma_proc AAudioStream_getFormat;
2299 ma_proc AAudioStream_getChannelCount;
2300 ma_proc AAudioStream_getSampleRate;
2301 ma_proc AAudioStream_getBufferCapacityInFrames;
2302 ma_proc AAudioStream_getFramesPerDataCallback;
2303 ma_proc AAudioStream_getFramesPerBurst;
2304 ma_proc AAudioStream_requestStart;
2305 ma_proc AAudioStream_requestStop;
2308 #ifdef MA_SUPPORT_OPENSL
2314 #ifdef MA_SUPPORT_WEBAUDIO
2320 #ifdef MA_SUPPORT_NULL
2397 float masterVolumeFactor;
2441 #ifdef MA_SUPPORT_WASAPI
2444 ma_ptr pAudioClientPlayback;
2445 ma_ptr pAudioClientCapture;
2448 ma_ptr pDeviceEnumerator;
2449 ma_IMMNotificationClient notificationClient;
2452 ma_uint32 actualBufferSizeInFramesPlayback;
2453 ma_uint32 actualBufferSizeInFramesCapture;
2455 ma_uint32 originalBufferSizeInMilliseconds;
2457 ma_bool32 hasDefaultPlaybackDeviceChanged;
2458 ma_bool32 hasDefaultCaptureDeviceChanged;
2467 #ifdef MA_SUPPORT_DSOUND
2471 ma_ptr pPlaybackPrimaryBuffer;
2477 #ifdef MA_SUPPORT_WINMM
2492 ma_uint8* pIntermediaryBufferPlayback;
2493 ma_uint8* pIntermediaryBufferCapture;
2497 #ifdef MA_SUPPORT_ALSA
2506 #ifdef MA_SUPPORT_PULSEAUDIO
2515 void* pMappedBufferPlayback;
2516 const void* pMappedBufferCapture;
2517 ma_uint32 mappedBufferFramesRemainingPlayback;
2518 ma_uint32 mappedBufferFramesRemainingCapture;
2519 ma_uint32 mappedBufferFramesCapacityPlayback;
2520 ma_uint32 mappedBufferFramesCapacityCapture;
2524 #ifdef MA_SUPPORT_JACK
2530 float* pIntermediaryBufferPlayback;
2531 float* pIntermediaryBufferCapture;
2535 #ifdef MA_SUPPORT_COREAUDIO
2540 ma_ptr audioUnitPlayback;
2545 ma_uint32 originalBufferSizeInMilliseconds;
2554 #ifdef MA_SUPPORT_SNDIO
2563 #ifdef MA_SUPPORT_AUDIO4
2570 #ifdef MA_SUPPORT_OSS
2577 #ifdef MA_SUPPORT_AAUDIO
2585 #ifdef MA_SUPPORT_OPENSL
2592 ma_ptr pAudioRecorderObj;
2594 ma_ptr pBufferQueuePlayback;
2595 ma_ptr pBufferQueueCapture;
2603 #ifdef MA_SUPPORT_WEBAUDIO
2611 #ifdef MA_SUPPORT_NULL
2620 double priorRunTime;
2621 ma_uint32 currentPeriodFramesRemainingPlayback;
2622 ma_uint32 currentPeriodFramesRemainingCapture;
2630 #if defined(_MSC_VER) && !defined(__clang__)
2631 #pragma warning(pop)
2633 #pragma GCC diagnostic pop
3161 #ifndef MA_NO_DECODING
3288 double periodsPerSecond;
3311 #if defined(MINIAUDIO_IMPLEMENTATION) || defined(MA_IMPLEMENTATION)
3316 #if defined(MA_DEBUG_OUTPUT)
3327 #define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
3328 #define NOVIRTUALKEYCODES // VK_*
3329 #define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_*
3330 #define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
3331 #define NOSYSMETRICS // SM_*
3332 #define NOMENUS // MF_*
3333 #define NOICONS // IDI_*
3334 #define NOKEYSTATES // MK_*
3335 #define NOSYSCOMMANDS // SC_*
3336 #define NORASTEROPS // Binary and Tertiary raster ops
3337 #define NOSHOWWINDOW // SW_*
3338 #define OEMRESOURCE // OEM Resource values
3339 #define NOATOM // Atom Manager routines
3340 #define NOCLIPBOARD // Clipboard routines
3341 #define NOCOLOR // Screen colors
3342 #define NOCTLMGR // Control and Dialog routines
3343 #define NODRAWTEXT // DrawText() and DT_*
3344 #define NOGDI // All GDI defines and routines
3345 #define NOKERNEL // All KERNEL defines and routines
3346 #define NOUSER // All USER defines and routines
3348 #define NOMB // MB_* and MessageBox()
3349 #define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
3350 #define NOMETAFILE // typedef METAFILEPICT
3351 #define NOMINMAX // Macros min(a,b) and max(a,b)
3352 #define NOMSG // typedef MSG and associated routines
3353 #define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
3354 #define NOSCROLL // SB_* and scrolling routines
3355 #define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
3356 #define NOSOUND // Sound driver routines
3357 #define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
3358 #define NOWH // SetWindowsHook and WH_*
3359 #define NOWINOFFSETS // GWL_*, GCL_*, associated routines
3360 #define NOCOMM // COMM driver routines
3361 #define NOKANJI // Kanji support stuff.
3362 #define NOHELP // Help engine interface.
3363 #define NOPROFILER // Profiler interface.
3364 #define NODEFERWINDOWPOS // DeferWindowPos routines
3365 #define NOMCX // Modem Configuration Extensions
3368 typedef struct tagMSG *LPMSG;
3370 #include <windows.h>
3373 typedef struct tagBITMAPINFOHEADER {
3379 DWORD biCompression;
3381 LONG biXPelsPerMeter;
3382 LONG biYPelsPerMeter;
3384 DWORD biClrImportant;
3385 } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
3387 #include <objbase.h>
3389 #include <mmsystem.h>
3392 #if defined(_MSC_VER) || defined(__TINYC__)
3393 #include "propidl.h"
3401 #if defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
3402 #include <mach/mach_time.h>
3406 #include <sys/time.h>
3407 #include <sys/types.h>
3412 #ifdef MA_EMSCRIPTEN
3413 #include <emscripten/emscripten.h>
3416 #if !defined(MA_64BIT) && !defined(MA_32BIT)
3426 #if !defined(MA_64BIT) && !defined(MA_32BIT)
3436 #if !defined(MA_64BIT) && !defined(MA_32BIT)
3438 #if INTPTR_MAX == INT64_MAX
3446 #if defined(__x86_64__) || defined(_M_X64)
3448 #elif defined(__i386) || defined(_M_IX86)
3450 #elif defined(__arm__) || defined(_M_ARM)
3455 #if !defined(MA_NO_AVX512) && defined(MA_NO_AVX2)
3456 #define MA_NO_AVX512
3460 #if defined(MA_X64) || defined(MA_X86)
3461 #if defined(_MSC_VER) && !defined(__clang__)
3463 #if _MSC_VER >= 1400 && !defined(MA_NO_SSE2)
3464 #define MA_SUPPORT_SSE2
3469 #if _MSC_VER >= 1700 && !defined(MA_NO_AVX2)
3470 #define MA_SUPPORT_AVX2
3472 #if _MSC_VER >= 1910 && !defined(MA_NO_AVX512)
3473 #define MA_SUPPORT_AVX512
3477 #if defined(__SSE2__) && !defined(MA_NO_SSE2)
3478 #define MA_SUPPORT_SSE2
3483 #if defined(__AVX2__) && !defined(MA_NO_AVX2)
3484 #define MA_SUPPORT_AVX2
3486 #if defined(__AVX512F__) && !defined(MA_NO_AVX512)
3487 #define MA_SUPPORT_AVX512
3492 #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
3493 #if !defined(MA_SUPPORT_SSE2) && !defined(MA_NO_SSE2) && __has_include(<emmintrin.h>)
3494 #define MA_SUPPORT_SSE2
3499 #if !defined(MA_SUPPORT_AVX2) && !defined(MA_NO_AVX2) && __has_include(<immintrin.h>)
3500 #define MA_SUPPORT_AVX2
3502 #if !defined(MA_SUPPORT_AVX512) && !defined(MA_NO_AVX512) && __has_include(<zmmintrin.h>)
3503 #define MA_SUPPORT_AVX512
3507 #if defined(MA_SUPPORT_AVX512)
3508 #include <immintrin.h>
3509 #elif defined(MA_SUPPORT_AVX2) || defined(MA_SUPPORT_AVX)
3510 #include <immintrin.h>
3511 #elif defined(MA_SUPPORT_SSE2)
3512 #include <emmintrin.h>
3517 #if !defined(MA_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
3518 #define MA_SUPPORT_NEON
3522 #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
3523 #if !defined(MA_SUPPORT_NEON) && !defined(MA_NO_NEON) && __has_include(<arm_neon.h>)
3524 #define MA_SUPPORT_NEON
3528 #if defined(MA_SUPPORT_NEON)
3529 #include <arm_neon.h>
3533 #if defined(_MSC_VER)
3534 #pragma warning(push)
3535 #pragma warning(disable:4752)
3538 #if defined(MA_X64) || defined(MA_X86)
3539 #if defined(_MSC_VER) && !defined(__clang__)
3540 #if _MSC_VER >= 1400
3542 static MA_INLINE void ma_cpuid(
int info[4],
int fid)
3550 #if _MSC_VER >= 1600 && (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219)
3551 static MA_INLINE unsigned __int64 ma_xgetbv(
int reg)
3553 return _xgetbv(reg);
3556 #define MA_NO_XGETBV
3558 #elif (defined(__GNUC__) || defined(__clang__)) && !defined(MA_ANDROID)
3559 static MA_INLINE void ma_cpuid(
int info[4],
int fid)
3568 #if defined(DRFLAC_X86) && defined(__PIC__)
3569 __asm__ __volatile__ (
3570 "xchg{l} {%%}ebx, %k1;"
3572 "xchg{l} {%%}ebx, %k1;"
3573 :
"=a"(info[0]),
"=&r"(info[1]),
"=c"(info[2]),
"=d"(info[3]) :
"a"(fid),
"c"(0)
3576 __asm__ __volatile__ (
3577 "cpuid" :
"=a"(info[0]),
"=b"(info[1]),
"=c"(info[2]),
"=d"(info[3]) :
"a"(fid),
"c"(0)
3587 __asm__ __volatile__ (
3588 "xgetbv" :
"=a"(lo),
"=d"(hi) :
"c"(reg)
3595 #define MA_NO_XGETBV
3599 #define MA_NO_XGETBV
3604 #if defined(MA_SUPPORT_SSE2)
3605 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_SSE2)
3608 #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)
3611 #if defined(MA_NO_CPUID)
3616 return (info[3] & (1 << 26)) != 0;
3630 #if defined(MA_SUPPORT_AVX)
3631 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX)
3632 #if defined(_AVX_) || defined(__AVX__)
3636 #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
3641 if (((info[2] & (1 << 27)) != 0) && ((info[2] & (1 << 28)) != 0)) {
3643 if ((xrc & 0x06) == 0x06) {
3664 #if defined(MA_SUPPORT_AVX2)
3665 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX2)
3666 #if defined(_AVX2_) || defined(__AVX2__)
3670 #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
3677 if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 5)) != 0)) {
3679 if ((xrc & 0x06) == 0x06) {
3699 #if defined(MA_SUPPORT_AVX512)
3700 #if (defined(MA_X64) || defined(MA_X86)) && !defined(MA_NO_AVX512)
3701 #if defined(__AVX512F__)
3705 #if defined(MA_NO_CPUID) || defined(MA_NO_XGETBV)
3712 if (((info1[2] & (1 << 27)) != 0) && ((info7[1] & (1 << 16)) != 0)) {
3714 if ((xrc & 0xE6) == 0xE6) {
3734 #if defined(MA_SUPPORT_NEON)
3735 #if defined(MA_ARM) && !defined(MA_NO_NEON)
3736 #if (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
3753 #if defined(MA_X86) || defined(MA_X64)
3757 return (*(
char*)&n) == 1;
3763 return !ma_is_little_endian();
3767 #ifndef MA_COINIT_VALUE
3768 #define MA_COINIT_VALUE 0
3774 #define MA_PI 3.14159265358979323846264f
3777 #define MA_PI_D 3.14159265358979323846264
3780 #define MA_TAU 6.28318530717958647693f
3783 #define MA_TAU_D 6.28318530717958647693
3788 #ifndef MA_DEFAULT_FORMAT
3789 #define MA_DEFAULT_FORMAT ma_format_f32
3793 #ifndef MA_DEFAULT_CHANNELS
3794 #define MA_DEFAULT_CHANNELS 2
3798 #ifndef MA_DEFAULT_SAMPLE_RATE
3799 #define MA_DEFAULT_SAMPLE_RATE 48000
3803 #ifndef MA_DEFAULT_PERIODS
3804 #define MA_DEFAULT_PERIODS 3
3808 #ifndef MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_LOW_LATENCY
3809 #define MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_LOW_LATENCY (10*MA_DEFAULT_PERIODS)
3813 #ifndef MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_CONSERVATIVE
3814 #define MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_CONSERVATIVE (100*MA_DEFAULT_PERIODS)
3819 ma_uint32 g_maStandardSampleRatePriorities[] = {
3861 #define MA_MALLOC(sz) HeapAlloc(GetProcessHeap(), 0, (sz))
3863 #define MA_MALLOC(sz) malloc((sz))
3869 #define MA_REALLOC(p, sz) (((sz) > 0) ? ((p) ? HeapReAlloc(GetProcessHeap(), 0, (p), (sz)) : HeapAlloc(GetProcessHeap(), 0, (sz))) : ((VOID*)(size_t)(HeapFree(GetProcessHeap(), 0, (p)) & 0)))
3871 #define MA_REALLOC(p, sz) realloc((p), (sz))
3877 #define MA_FREE(p) HeapFree(GetProcessHeap(), 0, (p))
3879 #define MA_FREE(p) free((p))
3883 #ifndef MA_ZERO_MEMORY
3885 #define MA_ZERO_MEMORY(p, sz) ZeroMemory((p), (sz))
3887 #define MA_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
3891 #ifndef MA_COPY_MEMORY
3893 #define MA_COPY_MEMORY(dst, src, sz) CopyMemory((dst), (src), (sz))
3895 #define MA_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
3901 #define MA_ASSERT(condition) assert(condition)
3903 #define MA_ASSERT(condition) assert(condition)
3907 #define ma_zero_memory MA_ZERO_MEMORY
3908 #define ma_copy_memory MA_COPY_MEMORY
3909 #define ma_assert MA_ASSERT
3911 #define ma_zero_object(p) ma_zero_memory((p), sizeof(*(p)))
3912 #define ma_countof(x) (sizeof(x) / sizeof(x[0]))
3913 #define ma_max(x, y) (((x) > (y)) ? (x) : (y))
3914 #define ma_min(x, y) (((x) < (y)) ? (x) : (y))
3915 #define ma_clamp(x, lo, hi) (ma_max(lo, ma_min(x, hi)))
3916 #define ma_offset_ptr(p, offset) (((ma_uint8*)(p)) + (offset))
3918 #define ma_buffer_frame_capacity(buffer, channels, format) (sizeof(buffer) / ma_get_bytes_per_sample(format) / (channels))
3928 int ma_strcpy_s(
char*
dst,
size_t dstSizeInBytes,
const char*
src)
3935 if (dstSizeInBytes == 0) {
3943 for (i = 0; i < dstSizeInBytes &&
src[i] !=
'\0'; ++i) {
3947 if (i < dstSizeInBytes) {
3956 int ma_strncpy_s(
char*
dst,
size_t dstSizeInBytes,
const char*
src,
size_t count)
3964 if (dstSizeInBytes == 0) {
3973 if (
count == ((
size_t)-1) ||
count >= dstSizeInBytes) {
3974 maxcount = dstSizeInBytes - 1;
3977 for (i = 0; i < maxcount &&
src[i] !=
'\0'; ++i) {
3981 if (
src[i] ==
'\0' || i ==
count ||
count == ((
size_t)-1)) {
3990 int ma_strcat_s(
char*
dst,
size_t dstSizeInBytes,
const char*
src)
3997 if (dstSizeInBytes == 0) {
4007 while (dstSizeInBytes > 0 &&
dst[0] !=
'\0') {
4009 dstSizeInBytes -= 1;
4012 if (dstSizeInBytes == 0) {
4017 while (dstSizeInBytes > 0 &&
src[0] !=
'\0') {
4019 dstSizeInBytes -= 1;
4022 if (dstSizeInBytes > 0) {
4032 int ma_strncat_s(
char*
dst,
size_t dstSizeInBytes,
const char*
src,
size_t count)
4039 if (dstSizeInBytes == 0) {
4048 while (dstSizeInBytes > 0 &&
dst[0] !=
'\0') {
4050 dstSizeInBytes -= 1;
4053 if (dstSizeInBytes == 0) {
4058 if (
count == ((
size_t)-1)) {
4059 count = dstSizeInBytes - 1;
4062 while (dstSizeInBytes > 0 &&
src[0] !=
'\0' &&
count > 0) {
4064 dstSizeInBytes -= 1;
4068 if (dstSizeInBytes > 0) {
4078 int ma_itoa_s(
int value,
char*
dst,
size_t dstSizeInBytes,
int radix)
4081 unsigned int valueU;
4084 if (
dst ==
NULL || dstSizeInBytes == 0) {
4087 if (radix < 2 || radix > 36) {
4092 sign = (
value < 0 && radix == 10) ? -1 : 1;
4103 int remainder = valueU % radix;
4104 if (remainder > 9) {
4105 *dstEnd = (
char)((remainder - 10) +
'a');
4107 *dstEnd = (
char)(remainder +
'0');
4111 dstSizeInBytes -= 1;
4113 }
while (dstSizeInBytes > 0 && valueU > 0);
4115 if (dstSizeInBytes == 0) {
4122 dstSizeInBytes -= 1;
4125 if (dstSizeInBytes == 0) {
4135 while (
dst < dstEnd) {
4147 int ma_strcmp(
const char* str1,
const char* str2)
4149 if (str1 == str2)
return 0;
4152 if (str1 ==
NULL)
return -1;
4153 if (str2 ==
NULL)
return 1;
4156 if (str1[0] ==
'\0') {
4159 if (str1[0] != str2[0]) {
4167 return ((
unsigned char*)str1)[0] - ((
unsigned char*)str2)[0];
4170 int ma_strappend(
char*
dst,
size_t dstSize,
const char* srcA,
const char* srcB)
4174 result = ma_strncpy_s(
dst, dstSize, srcA, (
size_t)-1);
4179 result = ma_strncat_s(
dst, dstSize, srcB, (
size_t)-1);
4187 char* ma_copy_string(
const char*
src)
4189 size_t sz = strlen(
src)+1;
4195 ma_strcpy_s(
dst, sz,
src);
4202 static MA_INLINE unsigned int ma_next_power_of_2(
unsigned int x)
4215 static MA_INLINE unsigned int ma_prev_power_of_2(
unsigned int x)
4217 return ma_next_power_of_2(
x) >> 1;
4220 static MA_INLINE unsigned int ma_round_to_power_of_2(
unsigned int x)
4222 unsigned int prev = ma_prev_power_of_2(
x);
4223 unsigned int next = ma_next_power_of_2(
x);
4224 if ((next -
x) > (
x - prev)) {
4231 static MA_INLINE unsigned int ma_count_set_bits(
unsigned int x)
4233 unsigned int count = 0;
4250 if (
x < -1)
return -1;
4251 if (
x > +1)
return +1;
4255 static MA_INLINE float ma_mix_f32(
float x,
float y,
float a)
4257 return x*(1-
a) +
y*
a;
4259 static MA_INLINE float ma_mix_f32_fast(
float x,
float y,
float a)
4267 #if defined(MA_SUPPORT_SSE2)
4268 static MA_INLINE __m128 ma_mix_f32_fast__sse2(__m128
x, __m128
y, __m128
a)
4270 return _mm_add_ps(
x, _mm_mul_ps(_mm_sub_ps(
y,
x),
a));
4273 #if defined(MA_SUPPORT_AVX2)
4274 static MA_INLINE __m256 ma_mix_f32_fast__avx2(__m256
x, __m256
y, __m256
a)
4276 return _mm256_add_ps(
x, _mm256_mul_ps(_mm256_sub_ps(
y,
x),
a));
4279 #if defined(MA_SUPPORT_AVX512)
4280 static MA_INLINE __m512 ma_mix_f32_fast__avx512(__m512
x, __m512
y, __m512
a)
4282 return _mm512_add_ps(
x, _mm512_mul_ps(_mm512_sub_ps(
y,
x),
a));
4285 #if defined(MA_SUPPORT_NEON)
4286 static MA_INLINE float32x4_t ma_mix_f32_fast__neon(float32x4_t
x, float32x4_t
y, float32x4_t
a)
4288 return vaddq_f32(
x, vmulq_f32(vsubq_f32(
y,
x),
a));
4293 static MA_INLINE double ma_mix_f64(
double x,
double y,
double a)
4295 return x*(1-
a) +
y*
a;
4297 static MA_INLINE double ma_mix_f64_fast(
double x,
double y,
double a)
4299 return x + (
y -
x)*
a;
4302 static MA_INLINE float ma_scale_to_range_f32(
float x,
float lo,
float hi)
4304 return lo +
x*(hi-lo);
4317 #define MA_LCG_M 2147483647
4318 #define MA_LCG_A 48271
4330 ma_int32 r = (MA_LCG_A * lcg + MA_LCG_C) % MA_LCG_M;
4340 double ma_rand_f64()
4342 return ma_rand_s32() / (double)0x7FFFFFFF;
4347 return (
float)ma_rand_f64();
4350 float ma_rand_range_f32(
float lo,
float hi)
4352 return ma_scale_to_range_f32(ma_rand_f32(), lo, hi);
4361 return lo + ma_rand_u32() / (0xFFFFFFFF / (hi - lo + 1) + 1);
4365 static MA_INLINE float ma_dither_f32_rectangle(
float ditherMin,
float ditherMax)
4367 return ma_rand_range_f32(ditherMin, ditherMax);
4370 static MA_INLINE float ma_dither_f32_triangle(
float ditherMin,
float ditherMax)
4372 float a = ma_rand_range_f32(ditherMin, 0);
4373 float b = ma_rand_range_f32(0, ditherMax);
4380 return ma_dither_f32_rectangle(ditherMin, ditherMax);
4383 return ma_dither_f32_triangle(ditherMin, ditherMax);
4392 ma_int32 a = ma_rand_range_s32(ditherMin, ditherMax);
4396 ma_int32 a = ma_rand_range_s32(ditherMin, 0);
4397 ma_int32 b = ma_rand_range_s32(0, ditherMax);
4409 void ma_split_buffer(
void* pBuffer,
size_t bufferSize,
size_t splitCount,
size_t alignment,
void** ppBuffersOut,
size_t* pSplitSizeOut)
4413 size_t unalignedBytes;
4416 if (pSplitSizeOut) {
4420 if (pBuffer ==
NULL || bufferSize == 0 || splitCount == 0) {
4424 if (alignment == 0) {
4429 pBufferAligned = (pBufferUnaligned + (alignment-1)) & ~(alignment-1);
4430 unalignedBytes = (size_t)(pBufferAligned - pBufferUnaligned);
4433 if (bufferSize >= unalignedBytes) {
4434 splitSize = (bufferSize - unalignedBytes) / splitCount;
4435 splitSize = splitSize & ~(alignment-1);
4438 if (ppBuffersOut !=
NULL) {
4440 for (i = 0; i < splitCount; ++i) {
4441 ppBuffersOut[i] = (
ma_uint8*)(pBufferAligned + (splitSize*i));
4445 if (pSplitSizeOut) {
4446 *pSplitSizeOut = splitSize;
4456 #if defined(__clang__)
4457 #if defined(__has_builtin)
4458 #if __has_builtin(__sync_swap)
4459 #define MA_HAS_SYNC_SWAP
4462 #elif defined(__GNUC__)
4463 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC__ >= 7)
4464 #define MA_HAS_GNUC_ATOMICS
4468 #if defined(_WIN32) && !defined(__GNUC__) && !defined(__clang__)
4469 #define ma_memory_barrier() MemoryBarrier()
4470 #define ma_atomic_exchange_32(a, b) InterlockedExchange((LONG*)a, (LONG)b)
4471 #define ma_atomic_exchange_64(a, b) InterlockedExchange64((LONGLONG*)a, (LONGLONG)b)
4472 #define ma_atomic_increment_32(a) InterlockedIncrement((LONG*)a)
4473 #define ma_atomic_decrement_32(a) InterlockedDecrement((LONG*)a)
4475 #define ma_memory_barrier() __sync_synchronize()
4476 #if defined(MA_HAS_SYNC_SWAP)
4477 #define ma_atomic_exchange_32(a, b) __sync_swap(a, b)
4478 #define ma_atomic_exchange_64(a, b) __sync_swap(a, b)
4479 #elif defined(MA_HAS_GNUC_ATOMICS)
4480 #define ma_atomic_exchange_32(a, b) (void)__atomic_exchange_n(a, b, __ATOMIC_ACQ_REL)
4481 #define ma_atomic_exchange_64(a, b) (void)__atomic_exchange_n(a, b, __ATOMIC_ACQ_REL)
4483 #define ma_atomic_exchange_32(a, b) __sync_synchronize(); (void)__sync_lock_test_and_set(a, b)
4484 #define ma_atomic_exchange_64(a, b) __sync_synchronize(); (void)__sync_lock_test_and_set(a, b)
4486 #define ma_atomic_increment_32(a) __sync_add_and_fetch(a, 1)
4487 #define ma_atomic_decrement_32(a) __sync_sub_and_fetch(a, 1)
4491 #define ma_atomic_exchange_ptr ma_atomic_exchange_64
4494 #define ma_atomic_exchange_ptr ma_atomic_exchange_32
4501 for (i = 0; i < ma_countof(g_maStandardSampleRatePriorities); ++i) {
4502 if (g_maStandardSampleRatePriorities[i] == sampleRate) {
4512 double srcRatio = (double)sampleRateOut / sampleRateIn;
4513 double frameCountOutF = (
ma_int64)frameCountIn * srcRatio;
4517 if ((frameCountOutF - (
ma_int64)frameCountOut) > 0.0) {
4521 return frameCountOut;
4533 #ifndef MA_NO_DEVICE_IO
4544 #ifndef MA_NO_RUNTIME_LINKING
4545 #if defined(MA_ANDROID) || defined(MA_EMSCRIPTEN)
4546 #define MA_NO_RUNTIME_LINKING
4554 #ifdef MA_ENABLE_WASAPI
4555 #define MA_HAS_WASAPI
4557 #ifdef MA_ENABLE_DSOUND
4558 #define MA_HAS_DSOUND
4560 #ifdef MA_ENABLE_WINMM
4561 #define MA_HAS_WINMM
4563 #ifdef MA_ENABLE_ALSA
4565 #ifdef MA_NO_RUNTIME_LINKING
4566 #ifdef __has_include
4567 #if !__has_include(<alsa/asoundlib.h>)
4573 #ifdef MA_ENABLE_PULSEAUDIO
4574 #define MA_HAS_PULSEAUDIO
4575 #ifdef MA_NO_RUNTIME_LINKING
4576 #ifdef __has_include
4577 #if !__has_include(<pulse/pulseaudio.h>)
4578 #undef MA_HAS_PULSEAUDIO
4583 #ifdef MA_ENABLE_JACK
4585 #ifdef MA_NO_RUNTIME_LINKING
4586 #ifdef __has_include
4587 #if !__has_include(<jack/jack.h>)
4593 #ifdef MA_ENABLE_COREAUDIO
4594 #define MA_HAS_COREAUDIO
4596 #ifdef MA_ENABLE_SNDIO
4597 #define MA_HAS_SNDIO
4599 #ifdef MA_ENABLE_AUDIO4
4600 #define MA_HAS_AUDIO4
4602 #ifdef MA_ENABLE_OSS
4605 #ifdef MA_ENABLE_AAUDIO
4606 #define MA_HAS_AAUDIO
4608 #ifdef MA_ENABLE_OPENSL
4609 #define MA_HAS_OPENSL
4611 #ifdef MA_ENABLE_WEBAUDIO
4612 #define MA_HAS_WEBAUDIO
4614 #ifdef MA_ENABLE_NULL
4636 default:
return "Unknown";
4665 #define MA_THREADCALL WINAPI
4666 typedef unsigned long ma_thread_result;
4668 #define MA_THREADCALL
4669 typedef void* ma_thread_result;
4671 typedef ma_thread_result (MA_THREADCALL * ma_thread_entry_proc)(
void* pData);
4674 typedef HRESULT (WINAPI * MA_PFN_CoInitializeEx)(LPVOID pvReserved, DWORD dwCoInit);
4675 typedef void (WINAPI * MA_PFN_CoUninitialize)();
4676 typedef HRESULT (WINAPI * MA_PFN_CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv);
4677 typedef void (WINAPI * MA_PFN_CoTaskMemFree)(LPVOID pv);
4678 typedef HRESULT (WINAPI * MA_PFN_PropVariantClear)(PROPVARIANT *pvar);
4679 typedef int (WINAPI * MA_PFN_StringFromGUID2)(
const GUID*
const rguid, LPOLESTR lpsz,
int cchMax);
4681 typedef HWND (WINAPI * MA_PFN_GetForegroundWindow)();
4682 typedef HWND (WINAPI * MA_PFN_GetDesktopWindow)();
4685 typedef LONG (WINAPI * MA_PFN_RegOpenKeyExA)(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
4686 typedef LONG (WINAPI * MA_PFN_RegCloseKey)(HKEY hKey);
4687 typedef LONG (WINAPI * MA_PFN_RegQueryValueExA)(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData);
4691 #define MA_STATE_UNINITIALIZED 0
4692 #define MA_STATE_STOPPED 1
4693 #define MA_STATE_STARTED 2
4694 #define MA_STATE_STARTING 3
4695 #define MA_STATE_STOPPING 4
4697 #define MA_DEFAULT_PLAYBACK_DEVICE_NAME "Default Playback Device"
4698 #define MA_DEFAULT_CAPTURE_DEVICE_NAME "Default Capture Device"
4709 default:
return "ERROR";
4716 if (pContext ==
NULL) {
4720 #if defined(MA_LOG_LEVEL)
4724 #if defined(MA_DEBUG_OUTPUT)
4732 onLog(pContext, pDevice, logLevel,
message);
4742 if (pContext ==
NULL) {
4743 if (pDevice !=
NULL) {
4744 pContext = pDevice->pContext;
4748 ma_log(pContext, pDevice, logLevel,
message);
4754 return ma_context_post_error(
NULL, pDevice, logLevel,
message, resultCode);
4764 LARGE_INTEGER g_ma_TimerFrequency = {{0}};
4765 void ma_timer_init(
ma_timer* pTimer)
4769 if (g_ma_TimerFrequency.QuadPart == 0) {
4770 QueryPerformanceFrequency(&g_ma_TimerFrequency);
4773 QueryPerformanceCounter(&
counter);
4777 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4780 if (!QueryPerformanceCounter(&
counter)) {
4784 return (
double)(
counter.QuadPart - pTimer->
counter) / g_ma_TimerFrequency.QuadPart;
4786 #elif defined(MA_APPLE) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
4788 void ma_timer_init(
ma_timer* pTimer)
4790 mach_timebase_info_data_t baseTime;
4791 mach_timebase_info(&baseTime);
4792 g_ma_TimerFrequency = (baseTime.denom * 1e9) / baseTime.numer;
4794 pTimer->
counter = mach_absolute_time();
4797 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4799 ma_uint64 newTimeCounter = mach_absolute_time();
4802 return (newTimeCounter - oldTimeCounter) / g_ma_TimerFrequency;
4804 #elif defined(MA_EMSCRIPTEN)
4805 void ma_timer_init(
ma_timer* pTimer)
4807 pTimer->
counterD = emscripten_get_now();
4810 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4812 return (emscripten_get_now() - pTimer->
counterD) / 1000;
4815 #if _POSIX_C_SOURCE >= 199309L
4816 #if defined(CLOCK_MONOTONIC)
4817 #define MA_CLOCK_ID CLOCK_MONOTONIC
4819 #define MA_CLOCK_ID CLOCK_REALTIME
4822 void ma_timer_init(
ma_timer* pTimer)
4824 struct timespec newTime;
4825 clock_gettime(MA_CLOCK_ID, &newTime);
4827 pTimer->
counter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
4830 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4835 struct timespec newTime;
4836 clock_gettime(MA_CLOCK_ID, &newTime);
4838 newTimeCounter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
4839 oldTimeCounter = pTimer->
counter;
4841 return (newTimeCounter - oldTimeCounter) / 1000000000.0;
4844 void ma_timer_init(
ma_timer* pTimer)
4846 struct timeval newTime;
4847 gettimeofday(&newTime,
NULL);
4849 pTimer->
counter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
4852 double ma_timer_get_time_in_seconds(
ma_timer* pTimer)
4857 struct timeval newTime;
4858 gettimeofday(&newTime,
NULL);
4860 newTimeCounter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
4861 oldTimeCounter = pTimer->
counter;
4863 return (newTimeCounter - oldTimeCounter) / 1000000.0;
4878 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_VERBOSE
4879 if (pContext !=
NULL) {
4881 ma_strappend(
message,
sizeof(
message),
"Loading library: ", filename);
4887 #ifdef MA_WIN32_DESKTOP
4891 WCHAR filenameW[4096];
4892 if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW,
sizeof(filenameW)) == 0) {
4906 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_INFO
4909 ma_strappend(
message,
sizeof(
message),
"Failed to load library: ", filename);
4921 FreeLibrary((HMODULE)
handle);
4933 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_VERBOSE
4934 if (pContext !=
NULL) {
4936 ma_strappend(
message,
sizeof(
message),
"Loading symbol: ", symbol);
4944 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
4945 #pragma GCC diagnostic push
4946 #pragma GCC diagnostic ignored "-Wpedantic"
4949 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
4950 #pragma GCC diagnostic pop
4954 #if MA_LOG_LEVEL >= MA_LOG_LEVEL_WARNING
4957 ma_strappend(
message,
sizeof(
message),
"Failed to load symbol: ", symbol);
4983 default:
return THREAD_PRIORITY_NORMAL;
4989 pThread->win32.hThread = CreateThread(
NULL, 0, entryProc, pData, 0,
NULL);
4990 if (pThread->win32.hThread ==
NULL) {
4994 SetThreadPriority((HANDLE)pThread->win32.hThread, ma_thread_priority_to_win32(pContext->
threadPriority));
4999 void ma_thread_wait__win32(
ma_thread* pThread)
5001 WaitForSingleObject(pThread->win32.hThread, INFINITE);
5004 void ma_sleep__win32(
ma_uint32 milliseconds)
5006 Sleep((DWORD)milliseconds);
5014 pMutex->win32.hMutex = CreateEventA(
NULL, FALSE, TRUE,
NULL);
5015 if (pMutex->win32.hMutex ==
NULL) {
5022 void ma_mutex_uninit__win32(
ma_mutex* pMutex)
5024 CloseHandle(pMutex->win32.hMutex);
5027 void ma_mutex_lock__win32(
ma_mutex* pMutex)
5029 WaitForSingleObject(pMutex->win32.hMutex, INFINITE);
5032 void ma_mutex_unlock__win32(
ma_mutex* pMutex)
5034 SetEvent(pMutex->win32.hMutex);
5042 pEvent->win32.hEvent = CreateEventW(
NULL, FALSE, FALSE,
NULL);
5043 if (pEvent->win32.hEvent ==
NULL) {
5050 void ma_event_uninit__win32(
ma_event* pEvent)
5052 CloseHandle(pEvent->win32.hEvent);
5057 return WaitForSingleObject(pEvent->win32.hEvent, INFINITE) == WAIT_OBJECT_0;
5062 return SetEvent(pEvent->win32.hEvent);
5070 typedef int (* ma_pthread_create_proc)(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (
void *),
void *arg);
5071 typedef int (* ma_pthread_join_proc)(pthread_t thread,
void **retval);
5072 typedef int (* ma_pthread_mutex_init_proc)(pthread_mutex_t *__mutex,
const pthread_mutexattr_t *__mutexattr);
5073 typedef int (* ma_pthread_mutex_destroy_proc)(pthread_mutex_t *__mutex);
5074 typedef int (* ma_pthread_mutex_lock_proc)(pthread_mutex_t *__mutex);
5075 typedef int (* ma_pthread_mutex_unlock_proc)(pthread_mutex_t *__mutex);
5076 typedef int (* ma_pthread_cond_init_proc)(pthread_cond_t *__restrict __cond,
const pthread_condattr_t *__restrict __cond_attr);
5077 typedef int (* ma_pthread_cond_destroy_proc)(pthread_cond_t *__cond);
5078 typedef int (* ma_pthread_cond_signal_proc)(pthread_cond_t *__cond);
5079 typedef int (* ma_pthread_cond_wait_proc)(pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex);
5080 typedef int (* ma_pthread_attr_init_proc)(pthread_attr_t *attr);
5081 typedef int (* ma_pthread_attr_destroy_proc)(pthread_attr_t *attr);
5082 typedef int (* ma_pthread_attr_setschedpolicy_proc)(pthread_attr_t *attr,
int policy);
5083 typedef int (* ma_pthread_attr_getschedparam_proc)(
const pthread_attr_t *attr,
struct sched_param *
param);
5084 typedef int (* ma_pthread_attr_setschedparam_proc)(pthread_attr_t *attr,
const struct sched_param *
param);
5089 pthread_attr_t* pAttr =
NULL;
5091 #if !defined(__EMSCRIPTEN__)
5093 pthread_attr_t attr;
5094 if (((ma_pthread_attr_init_proc)pContext->
posix.pthread_attr_init)(&attr) == 0) {
5098 if (((ma_pthread_attr_setschedpolicy_proc)pContext->
posix.pthread_attr_setschedpolicy)(&attr, SCHED_IDLE) == 0) {
5099 scheduler = SCHED_IDLE;
5104 if (((ma_pthread_attr_setschedpolicy_proc)pContext->
posix.pthread_attr_setschedpolicy)(&attr, SCHED_FIFO) == 0) {
5105 scheduler = SCHED_FIFO;
5110 scheduler = sched_getscheduler(0);
5114 if (scheduler != -1) {
5115 int priorityMin = sched_get_priority_min(scheduler);
5116 int priorityMax = sched_get_priority_max(scheduler);
5117 int priorityStep = (priorityMax - priorityMin) / 7;
5119 struct sched_param sched;
5120 if (((ma_pthread_attr_getschedparam_proc)pContext->
posix.pthread_attr_getschedparam)(&attr, &sched) == 0) {
5122 sched.sched_priority = priorityMin;
5124 sched.sched_priority = priorityMax;
5127 if (sched.sched_priority < priorityMin) {
5128 sched.sched_priority = priorityMin;
5130 if (sched.sched_priority > priorityMax) {
5131 sched.sched_priority = priorityMax;
5135 if (((ma_pthread_attr_setschedparam_proc)pContext->
posix.pthread_attr_setschedparam)(&attr, &sched) == 0) {
5141 ((ma_pthread_attr_destroy_proc)pContext->
posix.pthread_attr_destroy)(&attr);
5145 result = ((ma_pthread_create_proc)pContext->
posix.pthread_create)(&pThread->
posix.thread, pAttr, entryProc, pData);
5153 void ma_thread_wait__posix(
ma_thread* pThread)
5158 void ma_sleep__posix(
ma_uint32 milliseconds)
5160 #ifdef MA_EMSCRIPTEN
5164 #if _POSIX_C_SOURCE >= 199309L
5166 ts.tv_sec = milliseconds / 1000000;
5167 ts.tv_nsec = milliseconds % 1000000 * 1000000;
5168 nanosleep(&ts,
NULL);
5171 tv.tv_sec = milliseconds / 1000;
5172 tv.tv_usec = milliseconds % 1000 * 1000;
5181 int result = ((ma_pthread_mutex_init_proc)pContext->
posix.pthread_mutex_init)(&pMutex->
posix.mutex,
NULL);
5189 void ma_mutex_uninit__posix(
ma_mutex* pMutex)
5191 ((ma_pthread_mutex_destroy_proc)pMutex->
pContext->
posix.pthread_mutex_destroy)(&pMutex->
posix.mutex);
5194 void ma_mutex_lock__posix(
ma_mutex* pMutex)
5196 ((ma_pthread_mutex_lock_proc)pMutex->
pContext->
posix.pthread_mutex_lock)(&pMutex->
posix.mutex);
5199 void ma_mutex_unlock__posix(
ma_mutex* pMutex)
5201 ((ma_pthread_mutex_unlock_proc)pMutex->
pContext->
posix.pthread_mutex_unlock)(&pMutex->
posix.mutex);
5207 if (((ma_pthread_mutex_init_proc)pContext->
posix.pthread_mutex_init)(&pEvent->
posix.mutex,
NULL) != 0) {
5211 if (((ma_pthread_cond_init_proc)pContext->
posix.pthread_cond_init)(&pEvent->
posix.condition,
NULL) != 0) {
5215 pEvent->
posix.value = 0;
5219 void ma_event_uninit__posix(
ma_event* pEvent)
5221 ((ma_pthread_cond_destroy_proc)pEvent->
pContext->
posix.pthread_cond_destroy)(&pEvent->
posix.condition);
5222 ((ma_pthread_mutex_destroy_proc)pEvent->
pContext->
posix.pthread_mutex_destroy)(&pEvent->
posix.mutex);
5227 ((ma_pthread_mutex_lock_proc)pEvent->
pContext->
posix.pthread_mutex_lock)(&pEvent->
posix.mutex);
5229 while (pEvent->
posix.value == 0) {
5230 ((ma_pthread_cond_wait_proc)pEvent->
pContext->
posix.pthread_cond_wait)(&pEvent->
posix.condition, &pEvent->
posix.mutex);
5232 pEvent->
posix.value = 0;
5234 ((ma_pthread_mutex_unlock_proc)pEvent->
pContext->
posix.pthread_mutex_unlock)(&pEvent->
posix.mutex);
5241 ((ma_pthread_mutex_lock_proc)pEvent->
pContext->
posix.pthread_mutex_lock)(&pEvent->
posix.mutex);
5243 pEvent->
posix.value = 1;
5244 ((ma_pthread_cond_signal_proc)pEvent->
pContext->
posix.pthread_cond_signal)(&pEvent->
posix.condition);
5246 ((ma_pthread_mutex_unlock_proc)pEvent->
pContext->
posix.pthread_mutex_unlock)(&pEvent->
posix.mutex);
5254 if (pContext ==
NULL || pThread ==
NULL || entryProc ==
NULL) {
5261 return ma_thread_create__win32(pContext, pThread, entryProc, pData);
5264 return ma_thread_create__posix(pContext, pThread, entryProc, pData);
5270 if (pThread ==
NULL) {
5275 ma_thread_wait__win32(pThread);
5278 ma_thread_wait__posix(pThread);
5285 ma_sleep__win32(milliseconds);
5288 ma_sleep__posix(milliseconds);
5295 if (pContext ==
NULL || pMutex ==
NULL) {
5302 return ma_mutex_init__win32(pContext, pMutex);
5305 return ma_mutex_init__posix(pContext, pMutex);
5316 ma_mutex_uninit__win32(pMutex);
5319 ma_mutex_uninit__posix(pMutex);
5330 ma_mutex_lock__win32(pMutex);
5333 ma_mutex_lock__posix(pMutex);
5344 ma_mutex_unlock__win32(pMutex);
5347 ma_mutex_unlock__posix(pMutex);
5354 if (pContext ==
NULL || pEvent ==
NULL) {
5361 return ma_event_init__win32(pContext, pEvent);
5364 return ma_event_init__posix(pContext, pEvent);
5368 void ma_event_uninit(
ma_event* pEvent)
5375 ma_event_uninit__win32(pEvent);
5378 ma_event_uninit__posix(pEvent);
5389 return ma_event_wait__win32(pEvent);
5392 return ma_event_wait__posix(pEvent);
5403 return ma_event_signal__win32(pEvent);
5406 return ma_event_signal__posix(pEvent);
5420 if (sampleRateMin > sampleRateMax) {
5421 sampleRateMin = sampleRateMax;
5424 if (sampleRateMin == sampleRateMax) {
5425 return sampleRateMax;
5427 size_t iStandardRate;
5428 for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
5429 ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
5430 if (standardRate >= sampleRateMin && standardRate <= sampleRateMax) {
5431 return standardRate;
5445 size_t iStandardRate;
5447 for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
5448 ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
5451 if (sampleRateIn > standardRate) {
5452 diff = sampleRateIn - standardRate;
5454 diff = standardRate - sampleRateIn;
5458 return standardRate;
5461 if (closestDiff > diff) {
5463 closestRate = standardRate;
5473 return ma_max(1, (
ma_uint32)(baseBufferSize*scale));
5478 return bufferSizeInFrames / (sampleRate/1000);
5483 return bufferSizeInMilliseconds * (sampleRate/1000);
5489 return MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_LOW_LATENCY;
5491 return MA_BASE_BUFFER_SIZE_IN_MILLISECONDS_CONSERVATIVE;
5501 if (bufferSizeInMilliseconds == 0) {
5502 bufferSizeInMilliseconds = 1;
5505 sampleRateMS = (sampleRate/1000);
5506 if (sampleRateMS == 0) {
5510 return bufferSizeInMilliseconds * sampleRateMS;
5515 ma_uint32 fragmentSizeInFrames = bufferSizeInFrames / periods;
5516 return fragmentSizeInFrames * ma_get_bytes_per_frame(
format, channels);
5521 ma_zero_memory(p, frameCount * ma_get_bytes_per_frame(
format, channels));
5529 for (iSample = 0; iSample < sampleCount; iSample += 1) {
5530 p[iSample] = ma_clip_f32(p[iSample]);
5539 if (pSamplesOut ==
NULL || pSamplesIn ==
NULL) {
5543 for (iSample = 0; iSample < sampleCount; iSample += 1) {
5544 pSamplesOut[iSample] = (
ma_uint8)(pSamplesIn[iSample] * factor);
5552 if (pSamplesOut ==
NULL || pSamplesIn ==
NULL) {
5556 for (iSample = 0; iSample < sampleCount; iSample += 1) {
5557 pSamplesOut[iSample] = (
ma_int16)(pSamplesIn[iSample] * factor);
5567 if (pSamplesOut ==
NULL || pSamplesIn ==
NULL) {
5571 pSamplesOut8 = (
ma_uint8*)pSamplesOut;
5572 pSamplesIn8 = (
ma_uint8*)pSamplesIn;
5574 for (iSample = 0; iSample < sampleCount; iSample += 1) {
5578 sampleS32 = (
ma_int32)(sampleS32 * factor);
5580 pSamplesOut8[iSample*3+0] = (
ma_uint8)(((
ma_uint32)sampleS32 & 0x0000FF00) >> 8);
5581 pSamplesOut8[iSample*3+1] = (
ma_uint8)(((
ma_uint32)sampleS32 & 0x00FF0000) >> 16);
5582 pSamplesOut8[iSample*3+2] = (
ma_uint8)(((
ma_uint32)sampleS32 & 0xFF000000) >> 24);
5590 if (pSamplesOut ==
NULL || pSamplesIn ==
NULL) {
5594 for (iSample = 0; iSample < sampleCount; iSample += 1) {
5595 pSamplesOut[iSample] = (
ma_int32)(pSamplesIn[iSample] * factor);
5603 if (pSamplesOut ==
NULL || pSamplesIn ==
NULL) {
5607 for (iSample = 0; iSample < sampleCount; iSample += 1) {
5608 pSamplesOut[iSample] = pSamplesIn[iSample] * factor;
5708 return (
float)(20*log10(factor));
5713 return (
float)pow(10, gain/20.0);
5721 onData = pDevice->onData;
5723 if (!pDevice->noPreZeroedOutputBuffer && pFramesOut !=
NULL) {
5724 ma_zero_pcm_frames(pFramesOut, frameCount, pDevice->playback.format, pDevice->playback.channels);
5728 if (pFramesIn !=
NULL && pDevice->masterVolumeFactor < 1) {
5730 ma_uint32 bpfCapture = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
5731 ma_uint32 bpfPlayback = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
5733 while (totalFramesProcessed < frameCount) {
5734 ma_uint32 framesToProcessThisIteration = frameCount - totalFramesProcessed;
5735 if (framesToProcessThisIteration >
sizeof(tempFramesIn)/bpfCapture) {
5736 framesToProcessThisIteration =
sizeof(tempFramesIn)/bpfCapture;
5739 ma_copy_and_apply_volume_factor_pcm_frames(tempFramesIn, ma_offset_ptr(pFramesIn, totalFramesProcessed*bpfCapture), framesToProcessThisIteration, pDevice->capture.format, pDevice->capture.channels, pDevice->masterVolumeFactor);
5741 onData(pDevice, ma_offset_ptr(pFramesOut, totalFramesProcessed*bpfPlayback), tempFramesIn, framesToProcessThisIteration);
5743 totalFramesProcessed += framesToProcessThisIteration;
5746 onData(pDevice, pFramesOut, pFramesIn, frameCount);
5750 if (pFramesOut !=
NULL) {
5751 if (pDevice->masterVolumeFactor < 1) {
5752 if (pFramesIn ==
NULL) {
5757 if (!pDevice->noClip && pDevice->playback.format ==
ma_format_f32) {
5770 ma_assert(pDevice !=
NULL);
5772 ma_device__on_data(pDevice, pFramesOut,
NULL, frameCount);
5785 ma_assert(pDevice !=
NULL);
5787 if (pDevice->capture._dspFrameCount == 0) {
5791 framesToRead = frameCount;
5792 if (framesToRead > pDevice->capture._dspFrameCount) {
5793 framesToRead = pDevice->capture._dspFrameCount;
5796 bytesToRead = framesToRead * ma_get_bytes_per_frame(pConverter->formatConverterIn.config.formatIn, pConverter->channelRouter.config.channelsIn);
5799 if (pDevice->capture._dspFrames !=
NULL) {
5800 ma_copy_memory(pFramesOut, pDevice->capture._dspFrames, bytesToRead);
5801 pDevice->capture._dspFrames += bytesToRead;
5803 ma_zero_memory(pFramesOut, bytesToRead);
5806 pDevice->capture._dspFrameCount -= framesToRead;
5808 return framesToRead;
5817 ma_assert(pDevice !=
NULL);
5819 if (pDevice->playback._dspFrameCount == 0) {
5823 framesToRead = frameCount;
5824 if (framesToRead > pDevice->playback._dspFrameCount) {
5825 framesToRead = pDevice->playback._dspFrameCount;
5828 bytesToRead = framesToRead * ma_get_bytes_per_frame(pConverter->formatConverterIn.config.formatIn, pConverter->channelRouter.config.channelsIn);
5831 if (pDevice->playback._dspFrames !=
NULL) {
5832 ma_copy_memory(pFramesOut, pDevice->playback._dspFrames, bytesToRead);
5833 pDevice->playback._dspFrames += bytesToRead;
5835 ma_zero_memory(pFramesOut, bytesToRead);
5838 pDevice->playback._dspFrameCount -= framesToRead;
5840 return framesToRead;
5848 ma_assert(pDevice !=
NULL);
5849 ma_assert(frameCount > 0);
5850 ma_assert(pFramesOut !=
NULL);
5852 if (pDevice->playback.converter.isPassthrough) {
5853 ma_device__on_data(pDevice, pFramesOut,
NULL, frameCount);
5862 ma_assert(pDevice !=
NULL);
5863 ma_assert(frameCount > 0);
5864 ma_assert(pFrames !=
NULL);
5866 if (pDevice->capture.converter.isPassthrough) {
5867 ma_device__on_data(pDevice,
NULL, pFrames, frameCount);
5872 pDevice->capture._dspFrameCount = frameCount;
5873 pDevice->capture._dspFrames = (
const ma_uint8*)pFrames;
5875 chunkFrameCount =
sizeof(chunkBuffer) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
5879 if (framesJustRead == 0) {
5883 ma_device__on_data(pDevice,
NULL, chunkBuffer, framesJustRead);
5885 if (framesJustRead < chunkFrameCount) {
5896 ma_assert(pDevice !=
NULL);
5897 ma_assert(frameCount > 0);
5898 ma_assert(pFramesInInternalFormat !=
NULL);
5899 ma_assert(pRB !=
NULL);
5901 pDevice->capture._dspFrameCount = (
ma_uint32)frameCount;
5902 pDevice->capture._dspFrames = (
const ma_uint8*)pFramesInInternalFormat;
5908 void* pFramesInExternalFormat;
5916 if (framesToProcess == 0) {
5931 if (framesProcessed < framesToProcess) {
5942 ma_uint8 playbackFramesInExternalFormat[4096];
5947 ma_assert(pDevice !=
NULL);
5948 ma_assert(frameCount > 0);
5949 ma_assert(pFramesInInternalFormat !=
NULL);
5950 ma_assert(pRB !=
NULL);
5956 ma_zero_memory(silentInputFrames,
sizeof(silentInputFrames));
5959 totalFramesToReadFromClient = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->playback.internalSampleRate, frameCount);
5960 totalFramesReadFromClient = 0;
5961 while (totalFramesReadFromClient < totalFramesToReadFromClient &&
ma_device_is_started(pDevice)) {
5967 framesRemainingFromClient = (totalFramesToReadFromClient - totalFramesReadFromClient);
5968 framesToProcessFromClient =
sizeof(playbackFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
5969 if (framesToProcessFromClient > framesRemainingFromClient) {
5970 framesToProcessFromClient = framesRemainingFromClient;
5974 inputFrameCount = framesToProcessFromClient;
5977 if (inputFrameCount > 0) {
5979 ma_device__on_data(pDevice, playbackFramesInExternalFormat, pInputFrames, inputFrameCount);
5993 inputFrameCount = ma_min(
5994 sizeof(playbackFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels),
5995 sizeof(silentInputFrames) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels)
5998 ma_device__on_data(pDevice, playbackFramesInExternalFormat, silentInputFrames, inputFrameCount);
6002 pDevice->playback._dspFrameCount = inputFrameCount;
6003 pDevice->playback._dspFrames = (
const ma_uint8*)playbackFramesInExternalFormat;
6006 totalFramesReadFromClient += inputFrameCount;
6007 pFramesInInternalFormat = ma_offset_ptr(pFramesInInternalFormat, inputFrameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
6016 ma_atomic_exchange_32(&pDevice->state, newState);
6023 ma_atomic_exchange_32(&
state, pDevice->state);
6030 GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
6031 GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
6039 ma_assert(pContext !=
NULL);
6041 if (pID0 == pID1)
return MA_TRUE;
6043 if ((pID0 ==
NULL && pID1 !=
NULL) ||
6061 size_t nameBufferSize;
6063 } ma_context__try_get_device_name_by_id__enum_callback_data;
6067 ma_context__try_get_device_name_by_id__enum_callback_data* pData = (ma_context__try_get_device_name_by_id__enum_callback_data*)pUserData;
6068 ma_assert(pData !=
NULL);
6070 if (pData->deviceType == deviceType) {
6072 ma_strncpy_s(pData->pName, pData->nameBufferSize, pDeviceInfo->
name, (
size_t)-1);
6077 return !pData->foundDevice;
6088 ma_context__try_get_device_name_by_id__enum_callback_data
data;
6090 ma_assert(pContext !=
NULL);
6091 ma_assert(pName !=
NULL);
6093 if (pDeviceID ==
NULL) {
6097 data.deviceType = deviceType;
6098 data.pDeviceID = pDeviceID;
6100 data.nameBufferSize = nameBufferSize;
6107 if (!
data.foundDevice) {
6118 for (i = 0; i < ma_countof(g_maFormatPriorities); ++i) {
6119 if (g_maFormatPriorities[i] ==
format) {
6138 #define MA_DEVICE_OP_NONE__NULL 0
6139 #define MA_DEVICE_OP_START__NULL 1
6140 #define MA_DEVICE_OP_SUSPEND__NULL 2
6141 #define MA_DEVICE_OP_KILL__NULL 3
6143 ma_thread_result MA_THREADCALL ma_device_thread__null(
void* pData)
6146 ma_assert(pDevice !=
NULL);
6150 ma_event_wait(&pDevice->null_device.operationEvent);
6155 if (pDevice->null_device.operation == MA_DEVICE_OP_START__NULL) {
6156 ma_atomic_exchange_32(&pDevice->null_device.operation, MA_DEVICE_OP_NONE__NULL);
6159 ma_timer_init(&pDevice->null_device.timer);
6162 while (pDevice->null_device.operation != MA_DEVICE_OP_NONE__NULL && pDevice->null_device.operation != MA_DEVICE_OP_START__NULL) {
6167 ma_atomic_exchange_32(&pDevice->null_device.operationResult,
MA_SUCCESS);
6168 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6173 if (pDevice->null_device.operation == MA_DEVICE_OP_SUSPEND__NULL) {
6174 ma_atomic_exchange_32(&pDevice->null_device.operation, MA_DEVICE_OP_NONE__NULL);
6177 pDevice->null_device.priorRunTime += ma_timer_get_time_in_seconds(&pDevice->null_device.timer);
6178 ma_timer_init(&pDevice->null_device.timer);
6181 ma_atomic_exchange_32(&pDevice->null_device.operationResult,
MA_SUCCESS);
6182 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6187 if (pDevice->null_device.operation == MA_DEVICE_OP_KILL__NULL) {
6188 ma_atomic_exchange_32(&pDevice->null_device.operation, MA_DEVICE_OP_NONE__NULL);
6189 ma_atomic_exchange_32(&pDevice->null_device.operationResult,
MA_SUCCESS);
6190 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6195 if (pDevice->null_device.operation == MA_DEVICE_OP_NONE__NULL) {
6198 ma_event_signal(&pDevice->null_device.operationCompletionEvent);
6203 return (ma_thread_result)0;
6208 ma_atomic_exchange_32(&pDevice->null_device.operation, operation);
6209 if (!ma_event_signal(&pDevice->null_device.operationEvent)) {
6213 if (!ma_event_wait(&pDevice->null_device.operationCompletionEvent)) {
6217 return pDevice->null_device.operationResult;
6224 internalSampleRate = pDevice->capture.internalSampleRate;
6226 internalSampleRate = pDevice->playback.internalSampleRate;
6230 return (
ma_uint64)((pDevice->null_device.priorRunTime + ma_timer_get_time_in_seconds(&pDevice->null_device.timer)) * internalSampleRate);
6235 ma_assert(pContext !=
NULL);
6236 ma_assert(pID0 !=
NULL);
6237 ma_assert(pID1 !=
NULL);
6247 ma_assert(pContext !=
NULL);
6248 ma_assert(callback !=
NULL);
6253 ma_zero_object(&deviceInfo);
6254 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name),
"NULL Playback Device", (
size_t)-1);
6261 ma_zero_object(&deviceInfo);
6262 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name),
"NULL Capture Device", (
size_t)-1);
6273 ma_assert(pContext !=
NULL);
6281 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name),
"NULL Playback Device", (
size_t)-1);
6283 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name),
"NULL Capture Device", (
size_t)-1);
6288 for (iFormat = 0; iFormat < pDeviceInfo->
formatCount; ++iFormat) {
6303 void ma_device_uninit__null(
ma_device* pDevice)
6305 ma_assert(pDevice !=
NULL);
6308 ma_device_do_operation__null(pDevice, MA_DEVICE_OP_KILL__NULL);
6311 ma_event_uninit(&pDevice->null_device.operationCompletionEvent);
6312 ma_event_uninit(&pDevice->null_device.operationEvent);
6320 ma_assert(pDevice !=
NULL);
6322 ma_zero_object(&pDevice->null_device);
6329 if (bufferSizeInFrames == 0) {
6334 ma_strncpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name),
"NULL Capture Device", (
size_t)-1);
6338 pDevice->capture.internalBufferSizeInFrames = bufferSizeInFrames;
6339 pDevice->capture.internalPeriods = pConfig->
periods;
6342 ma_strncpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name),
"NULL Playback Device", (
size_t)-1);
6346 pDevice->playback.internalBufferSizeInFrames = bufferSizeInFrames;
6347 pDevice->playback.internalPeriods = pConfig->
periods;
6354 result = ma_event_init(pContext, &pDevice->null_device.operationEvent);
6359 result = ma_event_init(pContext, &pDevice->null_device.operationCompletionEvent);
6364 result = ma_thread_create(pContext, &pDevice->thread, ma_device_thread__null, pDevice);
6374 ma_assert(pDevice !=
NULL);
6376 ma_device_do_operation__null(pDevice, MA_DEVICE_OP_START__NULL);
6378 ma_atomic_exchange_32(&pDevice->null_device.isStarted,
MA_TRUE);
6384 ma_assert(pDevice !=
NULL);
6386 ma_device_do_operation__null(pDevice, MA_DEVICE_OP_SUSPEND__NULL);
6388 ma_atomic_exchange_32(&pDevice->null_device.isStarted,
MA_FALSE);
6398 if (pFramesWritten !=
NULL) {
6399 *pFramesWritten = 0;
6402 wasStartedOnEntry = pDevice->null_device.isStarted;
6405 totalPCMFramesProcessed = 0;
6406 while (totalPCMFramesProcessed < frameCount) {
6410 if (pDevice->null_device.currentPeriodFramesRemainingPlayback > 0) {
6411 ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
6412 ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingPlayback;
6413 if (framesToProcess > framesRemaining) {
6414 framesToProcess = framesRemaining;
6420 pDevice->null_device.currentPeriodFramesRemainingPlayback -= framesToProcess;
6421 totalPCMFramesProcessed += framesToProcess;
6425 if (pDevice->null_device.currentPeriodFramesRemainingPlayback == 0) {
6426 pDevice->null_device.currentPeriodFramesRemainingPlayback = 0;
6428 if (!pDevice->null_device.isStarted && !wasStartedOnEntry) {
6429 result = ma_device_start__null(pDevice);
6437 ma_assert(totalPCMFramesProcessed <= frameCount);
6438 if (totalPCMFramesProcessed == frameCount) {
6443 targetFrame = pDevice->null_device.lastProcessedFramePlayback;
6448 if (!pDevice->null_device.isStarted) {
6452 currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
6453 if (currentFrame >= targetFrame) {
6461 pDevice->null_device.lastProcessedFramePlayback += pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
6462 pDevice->null_device.currentPeriodFramesRemainingPlayback = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
6465 if (pFramesWritten !=
NULL) {
6466 *pFramesWritten = totalPCMFramesProcessed;
6477 if (pFramesRead !=
NULL) {
6482 totalPCMFramesProcessed = 0;
6483 while (totalPCMFramesProcessed < frameCount) {
6487 if (pDevice->null_device.currentPeriodFramesRemainingCapture > 0) {
6488 ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
6489 ma_uint32 framesRemaining = (frameCount - totalPCMFramesProcessed);
6490 ma_uint32 framesToProcess = pDevice->null_device.currentPeriodFramesRemainingCapture;
6491 if (framesToProcess > framesRemaining) {
6492 framesToProcess = framesRemaining;
6496 ma_zero_memory(ma_offset_ptr(pPCMFrames, totalPCMFramesProcessed*bpf), framesToProcess*bpf);
6498 pDevice->null_device.currentPeriodFramesRemainingCapture -= framesToProcess;
6499 totalPCMFramesProcessed += framesToProcess;
6503 if (pDevice->null_device.currentPeriodFramesRemainingCapture == 0) {
6504 pDevice->null_device.currentPeriodFramesRemainingCapture = 0;
6508 ma_assert(totalPCMFramesProcessed <= frameCount);
6509 if (totalPCMFramesProcessed == frameCount) {
6514 targetFrame = pDevice->null_device.lastProcessedFrameCapture + (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods);
6519 if (!pDevice->null_device.isStarted) {
6523 currentFrame = ma_device_get_total_run_time_in_frames__null(pDevice);
6524 if (currentFrame >= targetFrame) {
6532 pDevice->null_device.lastProcessedFrameCapture += pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
6533 pDevice->null_device.currentPeriodFramesRemainingCapture = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
6536 if (pFramesRead !=
NULL) {
6537 *pFramesRead = totalPCMFramesProcessed;
6548 ma_assert(pDevice !=
NULL);
6552 result = ma_device_start__null(pDevice);
6558 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
6559 switch (pDevice->type)
6566 ma_uint32 capturedDeviceDataCapInFrames =
sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
6567 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
6570 ma_uint32 periodSizeInFrames = ma_min(pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods, pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods);
6572 while (totalFramesProcessed < periodSizeInFrames) {
6573 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
6575 ma_uint32 framesToProcess = framesRemaining;
6576 if (framesToProcess > capturedDeviceDataCapInFrames) {
6577 framesToProcess = capturedDeviceDataCapInFrames;
6580 result = ma_device_read__null(pDevice, capturedDeviceData, framesToProcess, &framesProcessed);
6586 pDevice->capture._dspFrameCount = framesToProcess;
6587 pDevice->capture._dspFrames = capturedDeviceData;
6592 ma_uint32 capturedDataCapInFrames =
sizeof(capturedData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
6593 ma_uint32 playbackDataCapInFrames =
sizeof(playbackData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
6595 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
6597 if (capturedFramesToProcess == 0) {
6601 ma_device__on_data(pDevice, playbackData, capturedData, capturedFramesToProcess);
6604 pDevice->playback._dspFrameCount = capturedFramesToProcess;
6605 pDevice->playback._dspFrames = playbackData;
6608 if (playbackDeviceFramesCount == 0) {
6612 result = ma_device_write__null(pDevice, playbackDeviceData, playbackDeviceFramesCount,
NULL);
6618 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
6623 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
6634 totalFramesProcessed += framesProcessed;
6642 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
6643 ma_uint32 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
6645 while (framesReadThisPeriod < periodSizeInFrames) {
6646 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
6648 ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
6649 if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
6650 framesToReadThisIteration = intermediaryBufferSizeInFrames;
6653 result = ma_device_read__null(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
6659 ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
6661 framesReadThisPeriod += framesProcessed;
6669 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
6670 ma_uint32 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
6672 while (framesWrittenThisPeriod < periodSizeInFrames) {
6673 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
6675 ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
6676 if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
6677 framesToWriteThisIteration = intermediaryBufferSizeInFrames;
6680 ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
6682 result = ma_device_write__null(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
6688 framesWrittenThisPeriod += framesProcessed;
6700 ma_device_stop__null(pDevice);
6707 ma_assert(pContext !=
NULL);
6716 ma_assert(pContext !=
NULL);
6720 pContext->
onUninit = ma_context_uninit__null;
6722 pContext->
onEnumDevices = ma_context_enumerate_devices__null;
6741 #if defined(MA_WIN32)
6742 #if defined(MA_WIN32_DESKTOP)
6743 #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit)
6744 #define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
6745 #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) ((MA_PFN_CoCreateInstance)pContext->win32.CoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv)
6746 #define ma_CoTaskMemFree(pContext, pv) ((MA_PFN_CoTaskMemFree)pContext->win32.CoTaskMemFree)(pv)
6747 #define ma_PropVariantClear(pContext, pvar) ((MA_PFN_PropVariantClear)pContext->win32.PropVariantClear)(pvar)
6749 #define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) CoInitializeEx(pvReserved, dwCoInit)
6750 #define ma_CoUninitialize(pContext) CoUninitialize()
6751 #define ma_CoCreateInstance(pContext, rclsid, pUnkOuter, dwClsContext, riid, ppv) CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv)
6752 #define ma_CoTaskMemFree(pContext, pv) CoTaskMemFree(pv)
6753 #define ma_PropVariantClear(pContext, pvar) PropVariantClear(pvar)
6756 #if !defined(MAXULONG_PTR)
6757 typedef size_t DWORD_PTR;
6760 #if !defined(WAVE_FORMAT_44M08)
6761 #define WAVE_FORMAT_44M08 0x00000100
6762 #define WAVE_FORMAT_44S08 0x00000200
6763 #define WAVE_FORMAT_44M16 0x00000400
6764 #define WAVE_FORMAT_44S16 0x00000800
6765 #define WAVE_FORMAT_48M08 0x00001000
6766 #define WAVE_FORMAT_48S08 0x00002000
6767 #define WAVE_FORMAT_48M16 0x00004000
6768 #define WAVE_FORMAT_48S16 0x00008000
6769 #define WAVE_FORMAT_96M08 0x00010000
6770 #define WAVE_FORMAT_96S08 0x00020000
6771 #define WAVE_FORMAT_96M16 0x00040000
6772 #define WAVE_FORMAT_96S16 0x00080000
6775 #ifndef SPEAKER_FRONT_LEFT
6776 #define SPEAKER_FRONT_LEFT 0x1
6777 #define SPEAKER_FRONT_RIGHT 0x2
6778 #define SPEAKER_FRONT_CENTER 0x4
6779 #define SPEAKER_LOW_FREQUENCY 0x8
6780 #define SPEAKER_BACK_LEFT 0x10
6781 #define SPEAKER_BACK_RIGHT 0x20
6782 #define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
6783 #define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
6784 #define SPEAKER_BACK_CENTER 0x100
6785 #define SPEAKER_SIDE_LEFT 0x200
6786 #define SPEAKER_SIDE_RIGHT 0x400
6787 #define SPEAKER_TOP_CENTER 0x800
6788 #define SPEAKER_TOP_FRONT_LEFT 0x1000
6789 #define SPEAKER_TOP_FRONT_CENTER 0x2000
6790 #define SPEAKER_TOP_FRONT_RIGHT 0x4000
6791 #define SPEAKER_TOP_BACK_LEFT 0x8000
6792 #define SPEAKER_TOP_BACK_CENTER 0x10000
6793 #define SPEAKER_TOP_BACK_RIGHT 0x20000
6800 #if (defined(_MSC_VER) && !defined(_WAVEFORMATEXTENSIBLE_)) || defined(__DMC__)
6803 WAVEFORMATEX Format;
6806 WORD wValidBitsPerSample;
6807 WORD wSamplesPerBlock;
6810 DWORD dwChannelMask;
6812 } WAVEFORMATEXTENSIBLE;
6815 #ifndef WAVE_FORMAT_EXTENSIBLE
6816 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
6819 #ifndef WAVE_FORMAT_IEEE_FLOAT
6820 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
6823 GUID MA_GUID_NULL = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
6826 ma_uint8 ma_channel_id_to_ma__win32(DWORD
id)
6853 DWORD ma_channel_id_to_win32(DWORD
id)
6883 DWORD dwChannelMask = 0;
6886 for (iChannel = 0; iChannel < channels; ++iChannel) {
6887 dwChannelMask |= ma_channel_id_to_win32(channelMap[iChannel]);
6890 return dwChannelMask;
6896 if (channels == 1 && dwChannelMask == 0) {
6898 }
else if (channels == 2 && dwChannelMask == 0) {
6902 if (channels == 1 && (dwChannelMask & SPEAKER_FRONT_CENTER) != 0) {
6909 for (iBit = 0; iBit < 32; ++iBit) {
6910 DWORD bitValue = (dwChannelMask & (1UL << iBit));
6911 if (bitValue != 0) {
6913 channelMap[iChannel] = ma_channel_id_to_ma__win32(bitValue);
6922 ma_bool32 ma_is_guid_equal(
const void*
a,
const void*
b)
6924 return IsEqualGUID(*(
const GUID*)
a, *(
const GUID*)
b);
6927 #define ma_is_guid_equal(a, b) IsEqualGUID((const GUID*)a, (const GUID*)b)
6930 ma_format ma_format_from_WAVEFORMATEX(
const WAVEFORMATEX* pWF)
6932 ma_assert(pWF !=
NULL);
6934 if (pWF->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
6935 const WAVEFORMATEXTENSIBLE* pWFEX = (
const WAVEFORMATEXTENSIBLE*)pWF;
6936 if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_PCM)) {
6937 if (pWFEX->Samples.wValidBitsPerSample == 32) {
6940 if (pWFEX->Samples.wValidBitsPerSample == 24) {
6941 if (pWFEX->Format.wBitsPerSample == 32) {
6944 if (pWFEX->Format.wBitsPerSample == 24) {
6948 if (pWFEX->Samples.wValidBitsPerSample == 16) {
6951 if (pWFEX->Samples.wValidBitsPerSample == 8) {
6955 if (ma_is_guid_equal(&pWFEX->SubFormat, &MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
6956 if (pWFEX->Samples.wValidBitsPerSample == 32) {
6966 if (pWF->wFormatTag == WAVE_FORMAT_PCM) {
6967 if (pWF->wBitsPerSample == 32) {
6970 if (pWF->wBitsPerSample == 24) {
6973 if (pWF->wBitsPerSample == 16) {
6976 if (pWF->wBitsPerSample == 8) {
6980 if (pWF->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
6981 if (pWF->wBitsPerSample == 32) {
6984 if (pWF->wBitsPerSample == 64) {
7000 #ifdef MA_HAS_WASAPI
7002 #if defined(_MSC_VER)
7003 #pragma warning(push)
7004 #pragma warning(disable:4091)
7006 #include <audioclient.h>
7007 #include <mmdeviceapi.h>
7008 #if defined(_MSC_VER)
7009 #pragma warning(pop)
7017 #define MA_WIN32_WINNT_VISTA 0x0600
7018 #define MA_VER_MINORVERSION 0x01
7019 #define MA_VER_MAJORVERSION 0x02
7020 #define MA_VER_SERVICEPACKMAJOR 0x20
7021 #define MA_VER_GREATER_EQUAL 0x03
7024 DWORD dwOSVersionInfoSize;
7025 DWORD dwMajorVersion;
7026 DWORD dwMinorVersion;
7027 DWORD dwBuildNumber;
7029 WCHAR szCSDVersion[128];
7030 WORD wServicePackMajor;
7031 WORD wServicePackMinor;
7035 } ma_OSVERSIONINFOEXW;
7037 typedef BOOL (WINAPI * ma_PFNVerifyVersionInfoW) (ma_OSVERSIONINFOEXW* lpVersionInfo, DWORD dwTypeMask, DWORDLONG dwlConditionMask);
7038 typedef ULONGLONG (WINAPI * ma_PFNVerSetConditionMask)(ULONGLONG dwlConditionMask, DWORD dwTypeBitMask, BYTE dwConditionMask);
7041 #ifndef PROPERTYKEY_DEFINED
7042 #define PROPERTYKEY_DEFINED
7051 static MA_INLINE void ma_PropVariantInit(PROPVARIANT* pProp)
7053 ma_zero_object(pProp);
7057 const PROPERTYKEY MA_PKEY_Device_FriendlyName = {{0xA45C254E, 0xDF1C, 0x4EFD, {0x80, 0x20, 0x67, 0xD1, 0x46, 0xA8, 0x50, 0xE0}}, 14};
7058 const PROPERTYKEY MA_PKEY_AudioEngine_DeviceFormat = {{0xF19F064D, 0x82C, 0x4E27, {0xBC, 0x73, 0x68, 0x82, 0xA1, 0xBB, 0x8E, 0x4C}}, 0};
7060 const IID MA_IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
7061 const IID MA_IID_IAgileObject = {0x94EA2B94, 0xE9CC, 0x49E0, {0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90}};
7063 const IID MA_IID_IAudioClient = {0x1CB9AD4C, 0xDBFA, 0x4C32, {0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2}};
7064 const IID MA_IID_IAudioClient2 = {0x726778CD, 0xF60A, 0x4EDA, {0x82, 0xDE, 0xE4, 0x76, 0x10, 0xCD, 0x78, 0xAA}};
7065 const IID MA_IID_IAudioClient3 = {0x7ED4EE07, 0x8E67, 0x4CD4, {0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42}};
7066 const IID MA_IID_IAudioRenderClient = {0xF294ACFC, 0x3146, 0x4483, {0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}};
7067 const IID MA_IID_IAudioCaptureClient = {0xC8ADBD64, 0xE71E, 0x48A0, {0xA4, 0xDE, 0x18, 0x5C, 0x39, 0x5C, 0xD3, 0x17}};
7068 const IID MA_IID_IMMNotificationClient = {0x7991EEC9, 0x7E89, 0x4D85, {0x83, 0x90, 0x6C, 0x70, 0x3C, 0xEC, 0x60, 0xC0}};
7069 #ifndef MA_WIN32_DESKTOP
7070 const IID MA_IID_DEVINTERFACE_AUDIO_RENDER = {0xE6327CAD, 0xDCEC, 0x4949, {0xAE, 0x8A, 0x99, 0x1E, 0x97, 0x6A, 0x79, 0xD2}};
7071 const IID MA_IID_DEVINTERFACE_AUDIO_CAPTURE = {0x2EEF81BE, 0x33FA, 0x4800, {0x96, 0x70, 0x1C, 0xD4, 0x74, 0x97, 0x2C, 0x3F}};
7072 const IID MA_IID_IActivateAudioInterfaceCompletionHandler = {0x41D949AB, 0x9862, 0x444A, {0x80, 0xF6, 0xC2, 0x61, 0x33, 0x4D, 0xA5, 0xEB}};
7075 const IID MA_CLSID_MMDeviceEnumerator_Instance = {0xBCDE0395, 0xE52F, 0x467C, {0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E}};
7076 const IID MA_IID_IMMDeviceEnumerator_Instance = {0xA95664D2, 0x9614, 0x4F35, {0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6}};
7078 #define MA_CLSID_MMDeviceEnumerator MA_CLSID_MMDeviceEnumerator_Instance
7079 #define MA_IID_IMMDeviceEnumerator MA_IID_IMMDeviceEnumerator_Instance
7081 #define MA_CLSID_MMDeviceEnumerator &MA_CLSID_MMDeviceEnumerator_Instance
7082 #define MA_IID_IMMDeviceEnumerator &MA_IID_IMMDeviceEnumerator_Instance
7085 typedef struct ma_IUnknown ma_IUnknown;
7086 #ifdef MA_WIN32_DESKTOP
7087 #define MA_MM_DEVICE_STATE_ACTIVE 1
7088 #define MA_MM_DEVICE_STATE_DISABLED 2
7089 #define MA_MM_DEVICE_STATE_NOTPRESENT 4
7090 #define MA_MM_DEVICE_STATE_UNPLUGGED 8
7092 typedef struct ma_IMMDeviceEnumerator ma_IMMDeviceEnumerator;
7093 typedef struct ma_IMMDeviceCollection ma_IMMDeviceCollection;
7094 typedef struct ma_IMMDevice ma_IMMDevice;
7096 typedef struct ma_IActivateAudioInterfaceCompletionHandler ma_IActivateAudioInterfaceCompletionHandler;
7097 typedef struct ma_IActivateAudioInterfaceAsyncOperation ma_IActivateAudioInterfaceAsyncOperation;
7099 typedef struct ma_IPropertyStore ma_IPropertyStore;
7100 typedef struct ma_IAudioClient ma_IAudioClient;
7101 typedef struct ma_IAudioClient2 ma_IAudioClient2;
7102 typedef struct ma_IAudioClient3 ma_IAudioClient3;
7103 typedef struct ma_IAudioRenderClient ma_IAudioRenderClient;
7104 typedef struct ma_IAudioCaptureClient ma_IAudioCaptureClient;
7106 typedef ma_int64 MA_REFERENCE_TIME;
7108 #define MA_AUDCLNT_STREAMFLAGS_CROSSPROCESS 0x00010000
7109 #define MA_AUDCLNT_STREAMFLAGS_LOOPBACK 0x00020000
7110 #define MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK 0x00040000
7111 #define MA_AUDCLNT_STREAMFLAGS_NOPERSIST 0x00080000
7112 #define MA_AUDCLNT_STREAMFLAGS_RATEADJUST 0x00100000
7113 #define MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY 0x08000000
7114 #define MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
7115 #define MA_AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED 0x10000000
7116 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE 0x20000000
7117 #define MA_AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED 0x40000000
7120 #define MA_AUDCLNT_E_INVALID_DEVICE_PERIOD (-2004287456)
7121 #define MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED (-2004287463)
7122 #define MA_AUDCLNT_S_BUFFER_EMPTY (143196161)
7123 #define MA_AUDCLNT_E_DEVICE_IN_USE (-2004287478)
7126 #define MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY 1
7127 #define MA_AUDCLNT_BUFFERFLAGS_SILENT 2
7128 #define MA_AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR 4
7141 ma_eCommunications = 2
7146 MA_AUDCLNT_SHAREMODE_SHARED,
7147 MA_AUDCLNT_SHAREMODE_EXCLUSIVE
7148 } MA_AUDCLNT_SHAREMODE;
7152 MA_AudioCategory_Other = 0
7153 } MA_AUDIO_STREAM_CATEGORY;
7159 MA_AUDIO_STREAM_CATEGORY eCategory;
7160 } ma_AudioClientProperties;
7166 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IUnknown* pThis,
const IID*
const riid,
void** ppObject);
7167 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IUnknown* pThis);
7168 ULONG (STDMETHODCALLTYPE * Release) (ma_IUnknown* pThis);
7172 ma_IUnknownVtbl* lpVtbl;
7174 HRESULT ma_IUnknown_QueryInterface(ma_IUnknown* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7175 ULONG ma_IUnknown_AddRef(ma_IUnknown* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7176 ULONG ma_IUnknown_Release(ma_IUnknown* pThis) {
return pThis->lpVtbl->Release(pThis); }
7178 #ifdef MA_WIN32_DESKTOP
7183 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMNotificationClient* pThis,
const IID*
const riid,
void** ppObject);
7184 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMNotificationClient* pThis);
7185 ULONG (STDMETHODCALLTYPE * Release) (ma_IMMNotificationClient* pThis);
7188 HRESULT (STDMETHODCALLTYPE * OnDeviceStateChanged) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, DWORD dwNewState);
7189 HRESULT (STDMETHODCALLTYPE * OnDeviceAdded) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID);
7190 HRESULT (STDMETHODCALLTYPE * OnDeviceRemoved) (ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID);
7191 HRESULT (STDMETHODCALLTYPE * OnDefaultDeviceChanged)(ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID);
7192 HRESULT (STDMETHODCALLTYPE * OnPropertyValueChanged)(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID,
const PROPERTYKEY key);
7193 } ma_IMMNotificationClientVtbl;
7199 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceEnumerator* pThis,
const IID*
const riid,
void** ppObject);
7200 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceEnumerator* pThis);
7201 ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceEnumerator* pThis);
7204 HRESULT (STDMETHODCALLTYPE * EnumAudioEndpoints) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, DWORD dwStateMask, ma_IMMDeviceCollection** ppDevices);
7205 HRESULT (STDMETHODCALLTYPE * GetDefaultAudioEndpoint) (ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, ma_ERole role, ma_IMMDevice** ppEndpoint);
7206 HRESULT (STDMETHODCALLTYPE * GetDevice) (ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice);
7207 HRESULT (STDMETHODCALLTYPE * RegisterEndpointNotificationCallback) (ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient);
7208 HRESULT (STDMETHODCALLTYPE * UnregisterEndpointNotificationCallback)(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient);
7209 } ma_IMMDeviceEnumeratorVtbl;
7210 struct ma_IMMDeviceEnumerator
7212 ma_IMMDeviceEnumeratorVtbl* lpVtbl;
7214 HRESULT ma_IMMDeviceEnumerator_QueryInterface(ma_IMMDeviceEnumerator* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7215 ULONG ma_IMMDeviceEnumerator_AddRef(ma_IMMDeviceEnumerator* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7216 ULONG ma_IMMDeviceEnumerator_Release(ma_IMMDeviceEnumerator* pThis) {
return pThis->lpVtbl->Release(pThis); }
7217 HRESULT ma_IMMDeviceEnumerator_EnumAudioEndpoints(ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, DWORD dwStateMask, ma_IMMDeviceCollection** ppDevices) {
return pThis->lpVtbl->EnumAudioEndpoints(pThis, dataFlow, dwStateMask, ppDevices); }
7218 HRESULT ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(ma_IMMDeviceEnumerator* pThis, ma_EDataFlow dataFlow, ma_ERole role, ma_IMMDevice** ppEndpoint) {
return pThis->lpVtbl->GetDefaultAudioEndpoint(pThis, dataFlow, role, ppEndpoint); }
7219 HRESULT ma_IMMDeviceEnumerator_GetDevice(ma_IMMDeviceEnumerator* pThis, LPCWSTR pID, ma_IMMDevice** ppDevice) {
return pThis->lpVtbl->GetDevice(pThis, pID, ppDevice); }
7220 HRESULT ma_IMMDeviceEnumerator_RegisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient) {
return pThis->lpVtbl->RegisterEndpointNotificationCallback(pThis, pClient); }
7221 HRESULT ma_IMMDeviceEnumerator_UnregisterEndpointNotificationCallback(ma_IMMDeviceEnumerator* pThis, ma_IMMNotificationClient* pClient) {
return pThis->lpVtbl->UnregisterEndpointNotificationCallback(pThis, pClient); }
7228 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDeviceCollection* pThis,
const IID*
const riid,
void** ppObject);
7229 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDeviceCollection* pThis);
7230 ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDeviceCollection* pThis);
7233 HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IMMDeviceCollection* pThis, UINT* pDevices);
7234 HRESULT (STDMETHODCALLTYPE * Item) (ma_IMMDeviceCollection* pThis, UINT nDevice, ma_IMMDevice** ppDevice);
7235 } ma_IMMDeviceCollectionVtbl;
7236 struct ma_IMMDeviceCollection
7238 ma_IMMDeviceCollectionVtbl* lpVtbl;
7240 HRESULT ma_IMMDeviceCollection_QueryInterface(ma_IMMDeviceCollection* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7241 ULONG ma_IMMDeviceCollection_AddRef(ma_IMMDeviceCollection* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7242 ULONG ma_IMMDeviceCollection_Release(ma_IMMDeviceCollection* pThis) {
return pThis->lpVtbl->Release(pThis); }
7243 HRESULT ma_IMMDeviceCollection_GetCount(ma_IMMDeviceCollection* pThis, UINT* pDevices) {
return pThis->lpVtbl->GetCount(pThis, pDevices); }
7244 HRESULT ma_IMMDeviceCollection_Item(ma_IMMDeviceCollection* pThis, UINT nDevice, ma_IMMDevice** ppDevice) {
return pThis->lpVtbl->Item(pThis, nDevice, ppDevice); }
7251 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IMMDevice* pThis,
const IID*
const riid,
void** ppObject);
7252 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IMMDevice* pThis);
7253 ULONG (STDMETHODCALLTYPE * Release) (ma_IMMDevice* pThis);
7256 HRESULT (STDMETHODCALLTYPE * Activate) (ma_IMMDevice* pThis,
const IID*
const iid, DWORD dwClsCtx, PROPVARIANT* pActivationParams,
void** ppInterface);
7257 HRESULT (STDMETHODCALLTYPE * OpenPropertyStore)(ma_IMMDevice* pThis, DWORD stgmAccess, ma_IPropertyStore** ppProperties);
7258 HRESULT (STDMETHODCALLTYPE * GetId) (ma_IMMDevice* pThis, LPWSTR *pID);
7259 HRESULT (STDMETHODCALLTYPE * GetState) (ma_IMMDevice* pThis, DWORD *pState);
7263 ma_IMMDeviceVtbl* lpVtbl;
7265 HRESULT ma_IMMDevice_QueryInterface(ma_IMMDevice* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7266 ULONG ma_IMMDevice_AddRef(ma_IMMDevice* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7267 ULONG ma_IMMDevice_Release(ma_IMMDevice* pThis) {
return pThis->lpVtbl->Release(pThis); }
7268 HRESULT ma_IMMDevice_Activate(ma_IMMDevice* pThis,
const IID*
const iid, DWORD dwClsCtx, PROPVARIANT* pActivationParams,
void** ppInterface) {
return pThis->lpVtbl->Activate(pThis, iid, dwClsCtx, pActivationParams, ppInterface); }
7269 HRESULT ma_IMMDevice_OpenPropertyStore(ma_IMMDevice* pThis, DWORD stgmAccess, ma_IPropertyStore** ppProperties) {
return pThis->lpVtbl->OpenPropertyStore(pThis, stgmAccess, ppProperties); }
7270 HRESULT ma_IMMDevice_GetId(ma_IMMDevice* pThis, LPWSTR *pID) {
return pThis->lpVtbl->GetId(pThis, pID); }
7271 HRESULT ma_IMMDevice_GetState(ma_IMMDevice* pThis, DWORD *pState) {
return pThis->lpVtbl->GetState(pThis, pState); }
7277 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IActivateAudioInterfaceAsyncOperation* pThis,
const IID*
const riid,
void** ppObject);
7278 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
7279 ULONG (STDMETHODCALLTYPE * Release) (ma_IActivateAudioInterfaceAsyncOperation* pThis);
7282 HRESULT (STDMETHODCALLTYPE * GetActivateResult)(ma_IActivateAudioInterfaceAsyncOperation* pThis, HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface);
7283 } ma_IActivateAudioInterfaceAsyncOperationVtbl;
7284 struct ma_IActivateAudioInterfaceAsyncOperation
7286 ma_IActivateAudioInterfaceAsyncOperationVtbl* lpVtbl;
7288 HRESULT ma_IActivateAudioInterfaceAsyncOperation_QueryInterface(ma_IActivateAudioInterfaceAsyncOperation* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7289 ULONG ma_IActivateAudioInterfaceAsyncOperation_AddRef(ma_IActivateAudioInterfaceAsyncOperation* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7290 ULONG ma_IActivateAudioInterfaceAsyncOperation_Release(ma_IActivateAudioInterfaceAsyncOperation* pThis) {
return pThis->lpVtbl->Release(pThis); }
7291 HRESULT ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(ma_IActivateAudioInterfaceAsyncOperation* pThis, HRESULT *pActivateResult, ma_IUnknown** ppActivatedInterface) {
return pThis->lpVtbl->GetActivateResult(pThis, pActivateResult, ppActivatedInterface); }
7298 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IPropertyStore* pThis,
const IID*
const riid,
void** ppObject);
7299 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IPropertyStore* pThis);
7300 ULONG (STDMETHODCALLTYPE * Release) (ma_IPropertyStore* pThis);
7303 HRESULT (STDMETHODCALLTYPE * GetCount)(ma_IPropertyStore* pThis, DWORD* pPropCount);
7304 HRESULT (STDMETHODCALLTYPE * GetAt) (ma_IPropertyStore* pThis, DWORD propIndex, PROPERTYKEY* pPropKey);
7305 HRESULT (STDMETHODCALLTYPE * GetValue)(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey, PROPVARIANT* pPropVar);
7306 HRESULT (STDMETHODCALLTYPE * SetValue)(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey,
const PROPVARIANT*
const pPropVar);
7307 HRESULT (STDMETHODCALLTYPE * Commit) (ma_IPropertyStore* pThis);
7308 } ma_IPropertyStoreVtbl;
7309 struct ma_IPropertyStore
7311 ma_IPropertyStoreVtbl* lpVtbl;
7313 HRESULT ma_IPropertyStore_QueryInterface(ma_IPropertyStore* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7314 ULONG ma_IPropertyStore_AddRef(ma_IPropertyStore* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7315 ULONG ma_IPropertyStore_Release(ma_IPropertyStore* pThis) {
return pThis->lpVtbl->Release(pThis); }
7316 HRESULT ma_IPropertyStore_GetCount(ma_IPropertyStore* pThis, DWORD* pPropCount) {
return pThis->lpVtbl->GetCount(pThis, pPropCount); }
7317 HRESULT ma_IPropertyStore_GetAt(ma_IPropertyStore* pThis, DWORD propIndex, PROPERTYKEY* pPropKey) {
return pThis->lpVtbl->GetAt(pThis, propIndex, pPropKey); }
7318 HRESULT ma_IPropertyStore_GetValue(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey, PROPVARIANT* pPropVar) {
return pThis->lpVtbl->GetValue(pThis, pKey, pPropVar); }
7319 HRESULT ma_IPropertyStore_SetValue(ma_IPropertyStore* pThis,
const PROPERTYKEY*
const pKey,
const PROPVARIANT*
const pPropVar) {
return pThis->lpVtbl->SetValue(pThis, pKey, pPropVar); }
7320 HRESULT ma_IPropertyStore_Commit(ma_IPropertyStore* pThis) {
return pThis->lpVtbl->Commit(pThis); }
7327 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient* pThis,
const IID*
const riid,
void** ppObject);
7328 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient* pThis);
7329 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient* pThis);
7332 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
7333 HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient* pThis,
ma_uint32* pNumBufferFrames);
7334 HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency);
7335 HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient* pThis,
ma_uint32* pNumPaddingFrames);
7336 HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
7337 HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat);
7338 HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
7339 HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient* pThis);
7340 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient* pThis);
7341 HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient* pThis);
7342 HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient* pThis, HANDLE eventHandle);
7343 HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient* pThis,
const IID*
const riid,
void** pp);
7344 } ma_IAudioClientVtbl;
7345 struct ma_IAudioClient
7347 ma_IAudioClientVtbl* lpVtbl;
7349 HRESULT ma_IAudioClient_QueryInterface(ma_IAudioClient* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7350 ULONG ma_IAudioClient_AddRef(ma_IAudioClient* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7351 ULONG ma_IAudioClient_Release(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Release(pThis); }
7352 HRESULT ma_IAudioClient_Initialize(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid) {
return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
7353 HRESULT ma_IAudioClient_GetBufferSize(ma_IAudioClient* pThis,
ma_uint32* pNumBufferFrames) {
return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
7354 HRESULT ma_IAudioClient_GetStreamLatency(ma_IAudioClient* pThis, MA_REFERENCE_TIME* pLatency) {
return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
7355 HRESULT ma_IAudioClient_GetCurrentPadding(ma_IAudioClient* pThis,
ma_uint32* pNumPaddingFrames) {
return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
7356 HRESULT ma_IAudioClient_IsFormatSupported(ma_IAudioClient* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) {
return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
7357 HRESULT ma_IAudioClient_GetMixFormat(ma_IAudioClient* pThis, WAVEFORMATEX** ppDeviceFormat) {
return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
7358 HRESULT ma_IAudioClient_GetDevicePeriod(ma_IAudioClient* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) {
return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
7359 HRESULT ma_IAudioClient_Start(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Start(pThis); }
7360 HRESULT ma_IAudioClient_Stop(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Stop(pThis); }
7361 HRESULT ma_IAudioClient_Reset(ma_IAudioClient* pThis) {
return pThis->lpVtbl->Reset(pThis); }
7362 HRESULT ma_IAudioClient_SetEventHandle(ma_IAudioClient* pThis, HANDLE eventHandle) {
return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
7363 HRESULT ma_IAudioClient_GetService(ma_IAudioClient* pThis,
const IID*
const riid,
void** pp) {
return pThis->lpVtbl->GetService(pThis, riid, pp); }
7369 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient2* pThis,
const IID*
const riid,
void** ppObject);
7370 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient2* pThis);
7371 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient2* pThis);
7374 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
7375 HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient2* pThis,
ma_uint32* pNumBufferFrames);
7376 HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency);
7377 HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient2* pThis,
ma_uint32* pNumPaddingFrames);
7378 HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
7379 HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat);
7380 HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
7381 HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient2* pThis);
7382 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient2* pThis);
7383 HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient2* pThis);
7384 HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient2* pThis, HANDLE eventHandle);
7385 HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient2* pThis,
const IID*
const riid,
void** pp);
7388 HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable);
7389 HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient2* pThis,
const ma_AudioClientProperties* pProperties);
7390 HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient2* pThis,
const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
7391 } ma_IAudioClient2Vtbl;
7392 struct ma_IAudioClient2
7394 ma_IAudioClient2Vtbl* lpVtbl;
7396 HRESULT ma_IAudioClient2_QueryInterface(ma_IAudioClient2* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7397 ULONG ma_IAudioClient2_AddRef(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7398 ULONG ma_IAudioClient2_Release(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Release(pThis); }
7399 HRESULT ma_IAudioClient2_Initialize(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid) {
return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
7400 HRESULT ma_IAudioClient2_GetBufferSize(ma_IAudioClient2* pThis,
ma_uint32* pNumBufferFrames) {
return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
7401 HRESULT ma_IAudioClient2_GetStreamLatency(ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pLatency) {
return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
7402 HRESULT ma_IAudioClient2_GetCurrentPadding(ma_IAudioClient2* pThis,
ma_uint32* pNumPaddingFrames) {
return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
7403 HRESULT ma_IAudioClient2_IsFormatSupported(ma_IAudioClient2* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) {
return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
7404 HRESULT ma_IAudioClient2_GetMixFormat(ma_IAudioClient2* pThis, WAVEFORMATEX** ppDeviceFormat) {
return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
7405 HRESULT ma_IAudioClient2_GetDevicePeriod(ma_IAudioClient2* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) {
return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
7406 HRESULT ma_IAudioClient2_Start(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Start(pThis); }
7407 HRESULT ma_IAudioClient2_Stop(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Stop(pThis); }
7408 HRESULT ma_IAudioClient2_Reset(ma_IAudioClient2* pThis) {
return pThis->lpVtbl->Reset(pThis); }
7409 HRESULT ma_IAudioClient2_SetEventHandle(ma_IAudioClient2* pThis, HANDLE eventHandle) {
return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
7410 HRESULT ma_IAudioClient2_GetService(ma_IAudioClient2* pThis,
const IID*
const riid,
void** pp) {
return pThis->lpVtbl->GetService(pThis, riid, pp); }
7411 HRESULT ma_IAudioClient2_IsOffloadCapable(ma_IAudioClient2* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable) {
return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
7412 HRESULT ma_IAudioClient2_SetClientProperties(ma_IAudioClient2* pThis,
const ma_AudioClientProperties* pProperties) {
return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
7413 HRESULT ma_IAudioClient2_GetBufferSizeLimits(ma_IAudioClient2* pThis,
const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration) {
return pThis->lpVtbl->GetBufferSizeLimits(pThis, pFormat, eventDriven, pMinBufferDuration, pMaxBufferDuration); }
7420 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioClient3* pThis,
const IID*
const riid,
void** ppObject);
7421 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioClient3* pThis);
7422 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioClient3* pThis);
7425 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
7426 HRESULT (STDMETHODCALLTYPE * GetBufferSize) (ma_IAudioClient3* pThis,
ma_uint32* pNumBufferFrames);
7427 HRESULT (STDMETHODCALLTYPE * GetStreamLatency) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency);
7428 HRESULT (STDMETHODCALLTYPE * GetCurrentPadding)(ma_IAudioClient3* pThis,
ma_uint32* pNumPaddingFrames);
7429 HRESULT (STDMETHODCALLTYPE * IsFormatSupported)(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch);
7430 HRESULT (STDMETHODCALLTYPE * GetMixFormat) (ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat);
7431 HRESULT (STDMETHODCALLTYPE * GetDevicePeriod) (ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod);
7432 HRESULT (STDMETHODCALLTYPE * Start) (ma_IAudioClient3* pThis);
7433 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IAudioClient3* pThis);
7434 HRESULT (STDMETHODCALLTYPE * Reset) (ma_IAudioClient3* pThis);
7435 HRESULT (STDMETHODCALLTYPE * SetEventHandle) (ma_IAudioClient3* pThis, HANDLE eventHandle);
7436 HRESULT (STDMETHODCALLTYPE * GetService) (ma_IAudioClient3* pThis,
const IID*
const riid,
void** pp);
7439 HRESULT (STDMETHODCALLTYPE * IsOffloadCapable) (ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable);
7440 HRESULT (STDMETHODCALLTYPE * SetClientProperties)(ma_IAudioClient3* pThis,
const ma_AudioClientProperties* pProperties);
7441 HRESULT (STDMETHODCALLTYPE * GetBufferSizeLimits)(ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration);
7444 HRESULT (STDMETHODCALLTYPE * GetSharedModeEnginePeriod) (ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat, UINT32* pDefaultPeriodInFrames, UINT32* pFundamentalPeriodInFrames, UINT32* pMinPeriodInFrames, UINT32* pMaxPeriodInFrames);
7445 HRESULT (STDMETHODCALLTYPE * GetCurrentSharedModeEnginePeriod)(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, UINT32* pCurrentPeriodInFrames);
7446 HRESULT (STDMETHODCALLTYPE * InitializeSharedAudioStream) (ma_IAudioClient3* pThis, DWORD streamFlags, UINT32 periodInFrames,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid);
7447 } ma_IAudioClient3Vtbl;
7448 struct ma_IAudioClient3
7450 ma_IAudioClient3Vtbl* lpVtbl;
7452 HRESULT ma_IAudioClient3_QueryInterface(ma_IAudioClient3* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7453 ULONG ma_IAudioClient3_AddRef(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7454 ULONG ma_IAudioClient3_Release(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Release(pThis); }
7455 HRESULT ma_IAudioClient3_Initialize(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode, DWORD streamFlags, MA_REFERENCE_TIME bufferDuration, MA_REFERENCE_TIME periodicity,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGuid) {
return pThis->lpVtbl->Initialize(pThis, shareMode, streamFlags, bufferDuration, periodicity, pFormat, pAudioSessionGuid); }
7456 HRESULT ma_IAudioClient3_GetBufferSize(ma_IAudioClient3* pThis,
ma_uint32* pNumBufferFrames) {
return pThis->lpVtbl->GetBufferSize(pThis, pNumBufferFrames); }
7457 HRESULT ma_IAudioClient3_GetStreamLatency(ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pLatency) {
return pThis->lpVtbl->GetStreamLatency(pThis, pLatency); }
7458 HRESULT ma_IAudioClient3_GetCurrentPadding(ma_IAudioClient3* pThis,
ma_uint32* pNumPaddingFrames) {
return pThis->lpVtbl->GetCurrentPadding(pThis, pNumPaddingFrames); }
7459 HRESULT ma_IAudioClient3_IsFormatSupported(ma_IAudioClient3* pThis, MA_AUDCLNT_SHAREMODE shareMode,
const WAVEFORMATEX* pFormat, WAVEFORMATEX** ppClosestMatch) {
return pThis->lpVtbl->IsFormatSupported(pThis, shareMode, pFormat, ppClosestMatch); }
7460 HRESULT ma_IAudioClient3_GetMixFormat(ma_IAudioClient3* pThis, WAVEFORMATEX** ppDeviceFormat) {
return pThis->lpVtbl->GetMixFormat(pThis, ppDeviceFormat); }
7461 HRESULT ma_IAudioClient3_GetDevicePeriod(ma_IAudioClient3* pThis, MA_REFERENCE_TIME* pDefaultDevicePeriod, MA_REFERENCE_TIME* pMinimumDevicePeriod) {
return pThis->lpVtbl->GetDevicePeriod(pThis, pDefaultDevicePeriod, pMinimumDevicePeriod); }
7462 HRESULT ma_IAudioClient3_Start(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Start(pThis); }
7463 HRESULT ma_IAudioClient3_Stop(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Stop(pThis); }
7464 HRESULT ma_IAudioClient3_Reset(ma_IAudioClient3* pThis) {
return pThis->lpVtbl->Reset(pThis); }
7465 HRESULT ma_IAudioClient3_SetEventHandle(ma_IAudioClient3* pThis, HANDLE eventHandle) {
return pThis->lpVtbl->SetEventHandle(pThis, eventHandle); }
7466 HRESULT ma_IAudioClient3_GetService(ma_IAudioClient3* pThis,
const IID*
const riid,
void** pp) {
return pThis->lpVtbl->GetService(pThis, riid, pp); }
7467 HRESULT ma_IAudioClient3_IsOffloadCapable(ma_IAudioClient3* pThis, MA_AUDIO_STREAM_CATEGORY category, BOOL* pOffloadCapable) {
return pThis->lpVtbl->IsOffloadCapable(pThis, category, pOffloadCapable); }
7468 HRESULT ma_IAudioClient3_SetClientProperties(ma_IAudioClient3* pThis,
const ma_AudioClientProperties* pProperties) {
return pThis->lpVtbl->SetClientProperties(pThis, pProperties); }
7469 HRESULT ma_IAudioClient3_GetBufferSizeLimits(ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat, BOOL eventDriven, MA_REFERENCE_TIME* pMinBufferDuration, MA_REFERENCE_TIME* pMaxBufferDuration) {
return pThis->lpVtbl->GetBufferSizeLimits(pThis, pFormat, eventDriven, pMinBufferDuration, pMaxBufferDuration); }
7470 HRESULT ma_IAudioClient3_GetSharedModeEnginePeriod(ma_IAudioClient3* pThis,
const WAVEFORMATEX* pFormat, UINT32* pDefaultPeriodInFrames, UINT32* pFundamentalPeriodInFrames, UINT32* pMinPeriodInFrames, UINT32* pMaxPeriodInFrames) {
return pThis->lpVtbl->GetSharedModeEnginePeriod(pThis, pFormat, pDefaultPeriodInFrames, pFundamentalPeriodInFrames, pMinPeriodInFrames, pMaxPeriodInFrames); }
7471 HRESULT ma_IAudioClient3_GetCurrentSharedModeEnginePeriod(ma_IAudioClient3* pThis, WAVEFORMATEX** ppFormat, UINT32* pCurrentPeriodInFrames) {
return pThis->lpVtbl->GetCurrentSharedModeEnginePeriod(pThis, ppFormat, pCurrentPeriodInFrames); }
7472 HRESULT ma_IAudioClient3_InitializeSharedAudioStream(ma_IAudioClient3* pThis, DWORD streamFlags, UINT32 periodInFrames,
const WAVEFORMATEX* pFormat,
const GUID* pAudioSessionGUID) {
return pThis->lpVtbl->InitializeSharedAudioStream(pThis, streamFlags, periodInFrames, pFormat, pAudioSessionGUID); }
7479 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioRenderClient* pThis,
const IID*
const riid,
void** ppObject);
7480 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioRenderClient* pThis);
7481 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioRenderClient* pThis);
7484 HRESULT (STDMETHODCALLTYPE * GetBuffer) (ma_IAudioRenderClient* pThis,
ma_uint32 numFramesRequested, BYTE** ppData);
7485 HRESULT (STDMETHODCALLTYPE * ReleaseBuffer)(ma_IAudioRenderClient* pThis,
ma_uint32 numFramesWritten, DWORD dwFlags);
7486 } ma_IAudioRenderClientVtbl;
7487 struct ma_IAudioRenderClient
7489 ma_IAudioRenderClientVtbl* lpVtbl;
7491 HRESULT ma_IAudioRenderClient_QueryInterface(ma_IAudioRenderClient* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7492 ULONG ma_IAudioRenderClient_AddRef(ma_IAudioRenderClient* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7493 ULONG ma_IAudioRenderClient_Release(ma_IAudioRenderClient* pThis) {
return pThis->lpVtbl->Release(pThis); }
7494 HRESULT ma_IAudioRenderClient_GetBuffer(ma_IAudioRenderClient* pThis,
ma_uint32 numFramesRequested, BYTE** ppData) {
return pThis->lpVtbl->GetBuffer(pThis, numFramesRequested, ppData); }
7495 HRESULT ma_IAudioRenderClient_ReleaseBuffer(ma_IAudioRenderClient* pThis,
ma_uint32 numFramesWritten, DWORD dwFlags) {
return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesWritten, dwFlags); }
7502 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioCaptureClient* pThis,
const IID*
const riid,
void** ppObject);
7503 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioCaptureClient* pThis);
7504 ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioCaptureClient* pThis);
7507 HRESULT (STDMETHODCALLTYPE * GetBuffer) (ma_IAudioCaptureClient* pThis, BYTE** ppData,
ma_uint32* pNumFramesToRead, DWORD* pFlags,
ma_uint64* pDevicePosition,
ma_uint64* pQPCPosition);
7508 HRESULT (STDMETHODCALLTYPE * ReleaseBuffer) (ma_IAudioCaptureClient* pThis,
ma_uint32 numFramesRead);
7509 HRESULT (STDMETHODCALLTYPE * GetNextPacketSize)(ma_IAudioCaptureClient* pThis,
ma_uint32* pNumFramesInNextPacket);
7510 } ma_IAudioCaptureClientVtbl;
7511 struct ma_IAudioCaptureClient
7513 ma_IAudioCaptureClientVtbl* lpVtbl;
7515 HRESULT ma_IAudioCaptureClient_QueryInterface(ma_IAudioCaptureClient* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
7516 ULONG ma_IAudioCaptureClient_AddRef(ma_IAudioCaptureClient* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
7517 ULONG ma_IAudioCaptureClient_Release(ma_IAudioCaptureClient* pThis) {
return pThis->lpVtbl->Release(pThis); }
7518 HRESULT ma_IAudioCaptureClient_GetBuffer(ma_IAudioCaptureClient* pThis, BYTE** ppData,
ma_uint32* pNumFramesToRead, DWORD* pFlags,
ma_uint64* pDevicePosition,
ma_uint64* pQPCPosition) {
return pThis->lpVtbl->GetBuffer(pThis, ppData, pNumFramesToRead, pFlags, pDevicePosition, pQPCPosition); }
7519 HRESULT ma_IAudioCaptureClient_ReleaseBuffer(ma_IAudioCaptureClient* pThis,
ma_uint32 numFramesRead) {
return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesRead); }
7520 HRESULT ma_IAudioCaptureClient_GetNextPacketSize(ma_IAudioCaptureClient* pThis,
ma_uint32* pNumFramesInNextPacket) {
return pThis->lpVtbl->GetNextPacketSize(pThis, pNumFramesInNextPacket); }
7522 #ifndef MA_WIN32_DESKTOP
7523 #include <mmdeviceapi.h>
7524 typedef struct ma_completion_handler_uwp ma_completion_handler_uwp;
7529 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_completion_handler_uwp* pThis,
const IID*
const riid,
void** ppObject);
7530 ULONG (STDMETHODCALLTYPE * AddRef) (ma_completion_handler_uwp* pThis);
7531 ULONG (STDMETHODCALLTYPE * Release) (ma_completion_handler_uwp* pThis);
7534 HRESULT (STDMETHODCALLTYPE * ActivateCompleted)(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation);
7535 } ma_completion_handler_uwp_vtbl;
7536 struct ma_completion_handler_uwp
7538 ma_completion_handler_uwp_vtbl* lpVtbl;
7543 HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_QueryInterface(ma_completion_handler_uwp* pThis,
const IID*
const riid,
void** ppObject)
7549 if (!ma_is_guid_equal(riid, &MA_IID_IUnknown) && !ma_is_guid_equal(riid, &MA_IID_IActivateAudioInterfaceCompletionHandler) && !ma_is_guid_equal(riid, &MA_IID_IAgileObject)) {
7551 return E_NOINTERFACE;
7555 *ppObject = (
void*)pThis;
7556 ((ma_completion_handler_uwp_vtbl*)pThis->lpVtbl)->AddRef(pThis);
7560 ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_AddRef(ma_completion_handler_uwp* pThis)
7562 return (ULONG)ma_atomic_increment_32(&pThis->counter);
7565 ULONG STDMETHODCALLTYPE ma_completion_handler_uwp_Release(ma_completion_handler_uwp* pThis)
7567 ma_uint32 newRefCount = ma_atomic_decrement_32(&pThis->counter);
7568 if (newRefCount == 0) {
7572 return (ULONG)newRefCount;
7575 HRESULT STDMETHODCALLTYPE ma_completion_handler_uwp_ActivateCompleted(ma_completion_handler_uwp* pThis, ma_IActivateAudioInterfaceAsyncOperation* pActivateOperation)
7577 (
void)pActivateOperation;
7578 SetEvent(pThis->hEvent);
7583 static ma_completion_handler_uwp_vtbl g_maCompletionHandlerVtblInstance = {
7584 ma_completion_handler_uwp_QueryInterface,
7585 ma_completion_handler_uwp_AddRef,
7586 ma_completion_handler_uwp_Release,
7587 ma_completion_handler_uwp_ActivateCompleted
7590 ma_result ma_completion_handler_uwp_init(ma_completion_handler_uwp* pHandler)
7592 ma_assert(pHandler !=
NULL);
7593 ma_zero_object(pHandler);
7595 pHandler->lpVtbl = &g_maCompletionHandlerVtblInstance;
7596 pHandler->counter = 1;
7597 pHandler->hEvent = CreateEventA(
NULL, FALSE, FALSE,
NULL);
7598 if (pHandler->hEvent ==
NULL) {
7605 void ma_completion_handler_uwp_uninit(ma_completion_handler_uwp* pHandler)
7607 if (pHandler->hEvent !=
NULL) {
7608 CloseHandle(pHandler->hEvent);
7612 void ma_completion_handler_uwp_wait(ma_completion_handler_uwp* pHandler)
7614 WaitForSingleObject(pHandler->hEvent, INFINITE);
7619 #ifdef MA_WIN32_DESKTOP
7620 HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_QueryInterface(ma_IMMNotificationClient* pThis,
const IID*
const riid,
void** ppObject)
7626 if (!ma_is_guid_equal(riid, &MA_IID_IUnknown) && !ma_is_guid_equal(riid, &MA_IID_IMMNotificationClient)) {
7628 return E_NOINTERFACE;
7632 *ppObject = (
void*)pThis;
7633 ((ma_IMMNotificationClientVtbl*)pThis->lpVtbl)->AddRef(pThis);
7637 ULONG STDMETHODCALLTYPE ma_IMMNotificationClient_AddRef(ma_IMMNotificationClient* pThis)
7639 return (ULONG)ma_atomic_increment_32(&pThis->counter);
7642 ULONG STDMETHODCALLTYPE ma_IMMNotificationClient_Release(ma_IMMNotificationClient* pThis)
7644 ma_uint32 newRefCount = ma_atomic_decrement_32(&pThis->counter);
7645 if (newRefCount == 0) {
7649 return (ULONG)newRefCount;
7653 HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceStateChanged(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID, DWORD dwNewState)
7655 #ifdef MA_DEBUG_OUTPUT
7656 printf(
"IMMNotificationClient_OnDeviceStateChanged(pDeviceID=%S, dwNewState=%u)\n", (pDeviceID !=
NULL) ? pDeviceID : L
"(NULL)", (
unsigned int)dwNewState);
7665 HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceAdded(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID)
7667 #ifdef MA_DEBUG_OUTPUT
7668 printf(
"IMMNotificationClient_OnDeviceAdded(pDeviceID=%S)\n", (pDeviceID !=
NULL) ? pDeviceID : L
"(NULL)");
7677 HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDeviceRemoved(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID)
7679 #ifdef MA_DEBUG_OUTPUT
7680 printf(
"IMMNotificationClient_OnDeviceRemoved(pDeviceID=%S)\n", (pDeviceID !=
NULL) ? pDeviceID : L
"(NULL)");
7689 HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnDefaultDeviceChanged(ma_IMMNotificationClient* pThis, ma_EDataFlow dataFlow, ma_ERole role, LPCWSTR pDefaultDeviceID)
7691 #ifdef MA_DEBUG_OUTPUT
7692 printf(
"IMMNotificationClient_OnDefaultDeviceChanged(dataFlow=%d, role=%d, pDefaultDeviceID=%S)\n", dataFlow, role, (pDefaultDeviceID !=
NULL) ? pDefaultDeviceID : L
"(NULL)");
7696 if (role != ma_eConsole) {
7722 ma_atomic_exchange_32(&pThis->pDevice->wasapi.hasDefaultPlaybackDeviceChanged,
MA_TRUE);
7725 ma_atomic_exchange_32(&pThis->pDevice->wasapi.hasDefaultCaptureDeviceChanged,
MA_TRUE);
7728 (
void)pDefaultDeviceID;
7732 HRESULT STDMETHODCALLTYPE ma_IMMNotificationClient_OnPropertyValueChanged(ma_IMMNotificationClient* pThis, LPCWSTR pDeviceID,
const PROPERTYKEY key)
7734 #ifdef MA_DEBUG_OUTPUT
7735 printf(
"IMMNotificationClient_OnPropertyValueChanged(pDeviceID=%S)\n", (pDeviceID !=
NULL) ? pDeviceID : L
"(NULL)");
7744 static ma_IMMNotificationClientVtbl g_maNotificationCientVtbl = {
7745 ma_IMMNotificationClient_QueryInterface,
7746 ma_IMMNotificationClient_AddRef,
7747 ma_IMMNotificationClient_Release,
7748 ma_IMMNotificationClient_OnDeviceStateChanged,
7749 ma_IMMNotificationClient_OnDeviceAdded,
7750 ma_IMMNotificationClient_OnDeviceRemoved,
7751 ma_IMMNotificationClient_OnDefaultDeviceChanged,
7752 ma_IMMNotificationClient_OnPropertyValueChanged
7756 #ifdef MA_WIN32_DESKTOP
7757 typedef ma_IMMDevice ma_WASAPIDeviceInterface;
7759 typedef ma_IUnknown ma_WASAPIDeviceInterface;
7766 ma_assert(pContext !=
NULL);
7767 ma_assert(pID0 !=
NULL);
7768 ma_assert(pID1 !=
NULL);
7771 return memcmp(pID0->wasapi, pID1->wasapi,
sizeof(pID0->wasapi)) == 0;
7774 void ma_set_device_info_from_WAVEFORMATEX(
const WAVEFORMATEX* pWF,
ma_device_info* pInfo)
7776 ma_assert(pWF !=
NULL);
7777 ma_assert(pInfo !=
NULL);
7780 pInfo->
formats[0] = ma_format_from_WAVEFORMATEX(pWF);
7789 ma_assert(pAudioClient !=
NULL);
7790 ma_assert(pInfo !=
NULL);
7795 WAVEFORMATEX* pWF =
NULL;
7796 HRESULT hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pAudioClient, (WAVEFORMATEX**)&pWF);
7797 if (SUCCEEDED(hr)) {
7798 ma_set_device_info_from_WAVEFORMATEX(pWF, pInfo);
7805 #ifdef MA_WIN32_DESKTOP
7810 ma_IPropertyStore *pProperties;
7811 HRESULT hr = ma_IMMDevice_OpenPropertyStore((ma_IMMDevice*)pMMDevice, STGM_READ, &pProperties);
7812 if (SUCCEEDED(hr)) {
7814 ma_PropVariantInit(&var);
7816 hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_AudioEngine_DeviceFormat, &var);
7817 if (SUCCEEDED(hr)) {
7818 WAVEFORMATEX* pWF = (WAVEFORMATEX*)var.blob.pBlobData;
7819 ma_set_device_info_from_WAVEFORMATEX(pWF, pInfo);
7825 hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pWF,
NULL);
7826 ma_PropVariantClear(pContext, &var);
7843 WAVEFORMATEXTENSIBLE wf;
7849 ma_zero_object(&wf);
7850 wf.Format.cbSize =
sizeof(wf);
7851 wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
7852 wf.Format.nChannels = (WORD)channels;
7853 wf.dwChannelMask = ma_channel_map_to_channel_mask__win32(defaultChannelMap, channels);
7856 for (iFormat = 0; iFormat < ma_countof(formatsToSearch); ++iFormat) {
7861 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
7862 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
7863 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
7865 wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
7867 wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
7870 for (iSampleRate = 0; iSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iSampleRate) {
7871 wf.Format.nSamplesPerSec = g_maStandardSampleRatePriorities[iSampleRate];
7873 hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, (WAVEFORMATEX*)&wf,
NULL);
7874 if (SUCCEEDED(hr)) {
7875 ma_set_device_info_from_WAVEFORMATEX((WAVEFORMATEX*)&wf, pInfo);
7887 ma_IPropertyStore_Release(pProperties);
7892 ma_IPropertyStore_Release(pProperties);
7896 ma_IPropertyStore_Release(pProperties);
7909 #ifdef MA_WIN32_DESKTOP
7912 ma_IMMDeviceEnumerator* pDeviceEnumerator;
7915 ma_assert(pContext !=
NULL);
7916 ma_assert(ppMMDevice !=
NULL);
7918 hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator,
NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (
void**)&pDeviceEnumerator);
7923 if (pDeviceID ==
NULL) {
7924 hr = ma_IMMDeviceEnumerator_GetDefaultAudioEndpoint(pDeviceEnumerator, (deviceType ==
ma_device_type_capture) ? ma_eCapture : ma_eRender, ma_eConsole, ppMMDevice);
7926 hr = ma_IMMDeviceEnumerator_GetDevice(pDeviceEnumerator, pDeviceID->wasapi, ppMMDevice);
7929 ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
7942 ma_assert(pContext !=
NULL);
7943 ma_assert(pMMDevice !=
NULL);
7944 ma_assert(pInfo !=
NULL);
7947 hr = ma_IMMDevice_GetId(pMMDevice, &
id);
7948 if (SUCCEEDED(hr)) {
7949 size_t idlen = wcslen(
id);
7950 if (idlen+1 > ma_countof(pInfo->
id.wasapi)) {
7951 ma_CoTaskMemFree(pContext,
id);
7956 ma_copy_memory(pInfo->
id.wasapi,
id, idlen *
sizeof(
wchar_t));
7957 pInfo->
id.wasapi[idlen] =
'\0';
7959 ma_CoTaskMemFree(pContext,
id);
7963 ma_IPropertyStore *pProperties;
7964 hr = ma_IMMDevice_OpenPropertyStore(pMMDevice, STGM_READ, &pProperties);
7965 if (SUCCEEDED(hr)) {
7969 ma_PropVariantInit(&var);
7970 hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &var);
7971 if (SUCCEEDED(hr)) {
7972 WideCharToMultiByte(CP_UTF8, 0, var.pwszVal, -1, pInfo->
name,
sizeof(pInfo->
name), 0, FALSE);
7973 ma_PropVariantClear(pContext, &var);
7976 ma_IPropertyStore_Release(pProperties);
7981 if (!onlySimpleInfo) {
7982 ma_IAudioClient* pAudioClient;
7983 hr = ma_IMMDevice_Activate(pMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL,
NULL, (
void**)&pAudioClient);
7984 if (SUCCEEDED(hr)) {
7985 ma_result result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext, pMMDevice, pAudioClient, shareMode, pInfo);
7987 ma_IAudioClient_Release(pAudioClient);
8003 ma_assert(pContext !=
NULL);
8004 ma_assert(callback !=
NULL);
8006 hr = ma_IMMDeviceCollection_GetCount(pDeviceCollection, &deviceCount);
8011 for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
8013 ma_IMMDevice* pMMDevice;
8015 ma_zero_object(&deviceInfo);
8017 hr = ma_IMMDeviceCollection_Item(pDeviceCollection, iDevice, &pMMDevice);
8018 if (SUCCEEDED(hr)) {
8021 ma_IMMDevice_Release(pMMDevice);
8023 ma_bool32 cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
8035 #ifdef MA_WIN32_DESKTOP
8041 ma_assert(pContext !=
NULL);
8042 ma_assert(ppAudioClient !=
NULL);
8043 ma_assert(ppMMDevice !=
NULL);
8045 result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, ppMMDevice);
8050 hr = ma_IMMDevice_Activate(*ppMMDevice, &MA_IID_IAudioClient, CLSCTX_ALL,
NULL, (
void**)ppAudioClient);
8060 ma_IActivateAudioInterfaceAsyncOperation *pAsyncOp =
NULL;
8061 ma_completion_handler_uwp completionHandler;
8066 HRESULT activateResult;
8067 ma_IUnknown* pActivatedInterface;
8069 ma_assert(pContext !=
NULL);
8070 ma_assert(ppAudioClient !=
NULL);
8072 if (pDeviceID !=
NULL) {
8073 ma_copy_memory(&iid, pDeviceID->wasapi,
sizeof(iid));
8076 iid = MA_IID_DEVINTERFACE_AUDIO_RENDER;
8078 iid = MA_IID_DEVINTERFACE_AUDIO_CAPTURE;
8082 #if defined(__cplusplus)
8083 hr = StringFromIID(iid, &iidStr);
8085 hr = StringFromIID(&iid, &iidStr);
8091 result = ma_completion_handler_uwp_init(&completionHandler);
8093 ma_CoTaskMemFree(pContext, iidStr);
8097 #if defined(__cplusplus)
8098 hr = ActivateAudioInterfaceAsync(iidStr, MA_IID_IAudioClient,
NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
8100 hr = ActivateAudioInterfaceAsync(iidStr, &MA_IID_IAudioClient,
NULL, (IActivateAudioInterfaceCompletionHandler*)&completionHandler, (IActivateAudioInterfaceAsyncOperation**)&pAsyncOp);
8103 ma_completion_handler_uwp_uninit(&completionHandler);
8104 ma_CoTaskMemFree(pContext, iidStr);
8108 ma_CoTaskMemFree(pContext, iidStr);
8111 ma_completion_handler_uwp_wait(&completionHandler);
8112 ma_completion_handler_uwp_uninit(&completionHandler);
8114 hr = ma_IActivateAudioInterfaceAsyncOperation_GetActivateResult(pAsyncOp, &activateResult, &pActivatedInterface);
8115 ma_IActivateAudioInterfaceAsyncOperation_Release(pAsyncOp);
8117 if (FAILED(hr) || FAILED(activateResult)) {
8122 hr = ma_IUnknown_QueryInterface(pActivatedInterface, &MA_IID_IAudioClient, (
void**)ppAudioClient);
8127 if (ppActivatedInterface) {
8128 *ppActivatedInterface = pActivatedInterface;
8130 ma_IUnknown_Release(pActivatedInterface);
8139 #ifdef MA_WIN32_DESKTOP
8140 return ma_context_get_IAudioClient_Desktop__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
8142 return ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, ppAudioClient, ppDeviceInterface);
8150 #ifdef MA_WIN32_DESKTOP
8153 ma_IMMDeviceEnumerator* pDeviceEnumerator;
8154 ma_IMMDeviceCollection* pDeviceCollection;
8156 hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator,
NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (
void**)&pDeviceEnumerator);
8162 hr = ma_IMMDeviceEnumerator_EnumAudioEndpoints(pDeviceEnumerator, ma_eRender, MA_MM_DEVICE_STATE_ACTIVE, &pDeviceCollection);
8163 if (SUCCEEDED(hr)) {
8164 ma_context_enumerate_device_collection__wasapi(pContext, pDeviceCollection,
ma_device_type_playback, callback, pUserData);
8165 ma_IMMDeviceCollection_Release(pDeviceCollection);
8169 hr = ma_IMMDeviceEnumerator_EnumAudioEndpoints(pDeviceEnumerator, ma_eCapture, MA_MM_DEVICE_STATE_ACTIVE, &pDeviceCollection);
8170 if (SUCCEEDED(hr)) {
8171 ma_context_enumerate_device_collection__wasapi(pContext, pDeviceCollection,
ma_device_type_capture, callback, pUserData);
8172 ma_IMMDeviceCollection_Release(pDeviceCollection);
8175 ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
8191 ma_zero_object(&deviceInfo);
8192 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
8199 ma_zero_object(&deviceInfo);
8200 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
8211 #ifdef MA_WIN32_DESKTOP
8212 ma_IMMDevice* pMMDevice =
NULL;
8215 result = ma_context_get_MMDevice__wasapi(pContext, deviceType, pDeviceID, &pMMDevice);
8220 result = ma_context_get_device_info_from_MMDevice__wasapi(pContext, pMMDevice, shareMode,
MA_FALSE, pDeviceInfo);
8222 ma_IMMDevice_Release(pMMDevice);
8225 ma_IAudioClient* pAudioClient;
8230 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
8232 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
8240 result = ma_context_get_IAudioClient_UWP__wasapi(pContext, deviceType, pDeviceID, &pAudioClient,
NULL);
8245 result = ma_context_get_device_info_from_IAudioClient__wasapi(pContext,
NULL, pAudioClient, shareMode, pDeviceInfo);
8247 ma_IAudioClient_Release(pAudioClient);
8252 void ma_device_uninit__wasapi(
ma_device* pDevice)
8254 ma_assert(pDevice !=
NULL);
8256 #ifdef MA_WIN32_DESKTOP
8257 if (pDevice->wasapi.pDeviceEnumerator) {
8258 ((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator)->lpVtbl->UnregisterEndpointNotificationCallback((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator, &pDevice->wasapi.notificationClient);
8259 ma_IMMDeviceEnumerator_Release((ma_IMMDeviceEnumerator*)pDevice->wasapi.pDeviceEnumerator);
8263 if (pDevice->wasapi.pRenderClient) {
8264 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
8266 if (pDevice->wasapi.pCaptureClient) {
8267 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8270 if (pDevice->wasapi.pAudioClientPlayback) {
8271 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8273 if (pDevice->wasapi.pAudioClientCapture) {
8274 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8277 if (pDevice->wasapi.hEventPlayback) {
8278 CloseHandle(pDevice->wasapi.hEventPlayback);
8280 if (pDevice->wasapi.hEventCapture) {
8281 CloseHandle(pDevice->wasapi.hEventCapture);
8305 ma_IAudioClient* pAudioClient;
8306 ma_IAudioRenderClient* pRenderClient;
8307 ma_IAudioCaptureClient* pCaptureClient;
8316 char deviceName[256];
8317 } ma_device_init_internal_data__wasapi;
8323 const char* errorMsg =
"";
8324 MA_AUDCLNT_SHAREMODE shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
8325 DWORD streamFlags = 0;
8326 MA_REFERENCE_TIME bufferDurationInMicroseconds;
8328 WAVEFORMATEXTENSIBLE wf = {0};
8329 ma_WASAPIDeviceInterface* pDeviceInterface =
NULL;
8330 ma_IAudioClient2* pAudioClient2;
8333 ma_assert(pContext !=
NULL);
8334 ma_assert(pData !=
NULL);
8341 pData->pAudioClient =
NULL;
8342 pData->pRenderClient =
NULL;
8343 pData->pCaptureClient =
NULL;
8345 streamFlags = MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
8346 if (!pData->noAutoConvertSRC && !pData->usingDefaultSampleRate && pData->shareMode !=
ma_share_mode_exclusive) {
8347 streamFlags |= MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
8349 if (!pData->noDefaultQualitySRC && !pData->usingDefaultSampleRate && (streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) != 0) {
8350 streamFlags |= MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
8353 streamFlags |= MA_AUDCLNT_STREAMFLAGS_LOOPBACK;
8356 result = ma_context_get_IAudioClient__wasapi(pContext, deviceType, pDeviceID, &pData->pAudioClient, &pDeviceInterface);
8363 hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient2, (
void**)&pAudioClient2);
8364 if (SUCCEEDED(hr)) {
8365 BOOL isHardwareOffloadingSupported = 0;
8366 hr = ma_IAudioClient2_IsOffloadCapable(pAudioClient2, MA_AudioCategory_Other, &isHardwareOffloadingSupported);
8367 if (SUCCEEDED(hr) && isHardwareOffloadingSupported) {
8368 ma_AudioClientProperties clientProperties;
8369 ma_zero_object(&clientProperties);
8370 clientProperties.cbSize =
sizeof(clientProperties);
8371 clientProperties.bIsOffload = 1;
8372 clientProperties.eCategory = MA_AudioCategory_Other;
8373 ma_IAudioClient2_SetClientProperties(pAudioClient2, &clientProperties);
8376 pAudioClient2->lpVtbl->Release(pAudioClient2);
8382 #ifdef MA_WIN32_DESKTOP
8384 ma_IPropertyStore* pStore =
NULL;
8385 hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pStore);
8386 if (SUCCEEDED(hr)) {
8388 ma_PropVariantInit(&prop);
8389 hr = ma_IPropertyStore_GetValue(pStore, &MA_PKEY_AudioEngine_DeviceFormat, &prop);
8390 if (SUCCEEDED(hr)) {
8391 WAVEFORMATEX* pActualFormat = (WAVEFORMATEX*)prop.blob.pBlobData;
8392 hr = ma_IAudioClient_IsFormatSupported((ma_IAudioClient*)pData->pAudioClient, MA_AUDCLNT_SHAREMODE_EXCLUSIVE, pActualFormat,
NULL);
8393 if (SUCCEEDED(hr)) {
8394 ma_copy_memory(&wf, pActualFormat,
sizeof(WAVEFORMATEXTENSIBLE));
8397 ma_PropVariantClear(pContext, &prop);
8400 ma_IPropertyStore_Release(pStore);
8414 shareMode = MA_AUDCLNT_SHAREMODE_EXCLUSIVE;
8421 WAVEFORMATEXTENSIBLE* pNativeFormat =
NULL;
8422 hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pData->pAudioClient, (WAVEFORMATEX**)&pNativeFormat);
8426 ma_copy_memory(&wf, pNativeFormat,
sizeof(wf));
8430 ma_CoTaskMemFree(pContext, pNativeFormat);
8432 shareMode = MA_AUDCLNT_SHAREMODE_SHARED;
8437 errorMsg =
"[WASAPI] Failed to find best device mix format.";
8445 nativeSampleRate = wf.Format.nSamplesPerSec;
8446 if (streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) {
8447 wf.Format.nSamplesPerSec = pData->sampleRateIn;
8448 wf.Format.nAvgBytesPerSec = wf.Format.nSamplesPerSec * wf.Format.nBlockAlign;
8451 pData->formatOut = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)&wf);
8452 pData->channelsOut = wf.Format.nChannels;
8453 pData->sampleRateOut = wf.Format.nSamplesPerSec;
8456 ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
8459 pData->periodsOut = pData->periodsIn;
8460 pData->bufferSizeInFramesOut = pData->bufferSizeInFramesIn;
8461 if (pData->bufferSizeInFramesOut == 0) {
8465 bufferDurationInMicroseconds = ((
ma_uint64)pData->bufferSizeInFramesOut * 1000 * 1000) / wf.Format.nSamplesPerSec;
8469 if (shareMode == MA_AUDCLNT_SHAREMODE_EXCLUSIVE) {
8470 MA_REFERENCE_TIME bufferDuration = (bufferDurationInMicroseconds / pData->periodsOut) * 10;
8478 hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf,
NULL);
8479 if (hr == MA_AUDCLNT_E_INVALID_DEVICE_PERIOD) {
8480 if (bufferDuration > 500*10000) {
8483 if (bufferDuration == 0) {
8487 bufferDuration = bufferDuration * 2;
8495 if (hr == MA_AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
8497 hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &bufferSizeInFrames);
8498 if (SUCCEEDED(hr)) {
8499 bufferDuration = (MA_REFERENCE_TIME)((10000.0 * 1000 / wf.Format.nSamplesPerSec * bufferSizeInFrames) + 0.5);
8502 ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
8504 #ifdef MA_WIN32_DESKTOP
8505 hr = ma_IMMDevice_Activate(pDeviceInterface, &MA_IID_IAudioClient, CLSCTX_ALL,
NULL, (
void**)&pData->pAudioClient);
8507 hr = ma_IUnknown_QueryInterface(pDeviceInterface, &MA_IID_IAudioClient, (
void**)&pData->pAudioClient);
8510 if (SUCCEEDED(hr)) {
8511 hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, bufferDuration, (WAVEFORMATEX*)&wf,
NULL);
8518 if (hr == E_ACCESSDENIED) {
8519 errorMsg =
"[WASAPI] Failed to initialize device in exclusive mode. Access denied.",
result =
MA_ACCESS_DENIED;
8520 }
else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
8521 errorMsg =
"[WASAPI] Failed to initialize device in exclusive mode. Device in use.",
result =
MA_DEVICE_BUSY;
8529 if (shareMode == MA_AUDCLNT_SHAREMODE_SHARED) {
8540 #ifndef MA_WASAPI_NO_LOW_LATENCY_SHARED_MODE
8541 if ((streamFlags & MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM) == 0 || nativeSampleRate == wf.Format.nSamplesPerSec) {
8542 ma_IAudioClient3* pAudioClient3 =
NULL;
8543 hr = ma_IAudioClient_QueryInterface(pData->pAudioClient, &MA_IID_IAudioClient3, (
void**)&pAudioClient3);
8544 if (SUCCEEDED(hr)) {
8545 UINT32 defaultPeriodInFrames;
8546 UINT32 fundamentalPeriodInFrames;
8547 UINT32 minPeriodInFrames;
8548 UINT32 maxPeriodInFrames;
8549 hr = ma_IAudioClient3_GetSharedModeEnginePeriod(pAudioClient3, (WAVEFORMATEX*)&wf, &defaultPeriodInFrames, &fundamentalPeriodInFrames, &minPeriodInFrames, &maxPeriodInFrames);
8550 if (SUCCEEDED(hr)) {
8551 UINT32 desiredPeriodInFrames = pData->bufferSizeInFramesOut / pData->periodsOut;
8552 UINT32 actualPeriodInFrames = desiredPeriodInFrames;
8555 actualPeriodInFrames = actualPeriodInFrames / fundamentalPeriodInFrames;
8556 actualPeriodInFrames = actualPeriodInFrames * fundamentalPeriodInFrames;
8559 actualPeriodInFrames = ma_clamp(actualPeriodInFrames, minPeriodInFrames, maxPeriodInFrames);
8561 #if defined(MA_DEBUG_OUTPUT)
8562 printf(
"[WASAPI] Trying IAudioClient3_InitializeSharedAudioStream(actualPeriodInFrames=%d)\n", actualPeriodInFrames);
8563 printf(
" defaultPeriodInFrames=%d\n", defaultPeriodInFrames);
8564 printf(
" fundamentalPeriodInFrames=%d\n", fundamentalPeriodInFrames);
8565 printf(
" minPeriodInFrames=%d\n", minPeriodInFrames);
8566 printf(
" maxPeriodInFrames=%d\n", maxPeriodInFrames);
8570 if (actualPeriodInFrames >= desiredPeriodInFrames) {
8575 hr = ma_IAudioClient3_InitializeSharedAudioStream(pAudioClient3, streamFlags & ~(MA_AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | MA_AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY), actualPeriodInFrames, (WAVEFORMATEX*)&wf,
NULL);
8576 if (SUCCEEDED(hr)) {
8577 wasInitializedUsingIAudioClient3 =
MA_TRUE;
8578 pData->periodSizeInFramesOut = actualPeriodInFrames;
8579 pData->bufferSizeInFramesOut = actualPeriodInFrames * pData->periodsOut;
8580 #if defined(MA_DEBUG_OUTPUT)
8581 printf(
"[WASAPI] Using IAudioClient3\n");
8582 printf(
" periodSizeInFramesOut=%d\n", pData->periodSizeInFramesOut);
8583 printf(
" bufferSizeInFramesOut=%d\n", pData->bufferSizeInFramesOut);
8586 #if defined(MA_DEBUG_OUTPUT)
8587 printf(
"[WASAPI] IAudioClient3_InitializeSharedAudioStream failed. Falling back to IAudioClient.\n");
8591 #if defined(MA_DEBUG_OUTPUT)
8592 printf(
"[WASAPI] Not using IAudioClient3 because the desired period size is larger than the maximum supported by IAudioClient3.\n");
8596 #if defined(MA_DEBUG_OUTPUT)
8597 printf(
"[WASAPI] IAudioClient3_GetSharedModeEnginePeriod failed. Falling back to IAudioClient.\n");
8601 ma_IAudioClient3_Release(pAudioClient3);
8602 pAudioClient3 =
NULL;
8606 #if defined(MA_DEBUG_OUTPUT)
8607 printf(
"[WASAPI] Not using IAudioClient3 because MA_WASAPI_NO_LOW_LATENCY_SHARED_MODE is enabled.\n");
8612 if (!wasInitializedUsingIAudioClient3) {
8613 MA_REFERENCE_TIME bufferDuration = bufferDurationInMicroseconds*10;
8614 hr = ma_IAudioClient_Initialize((ma_IAudioClient*)pData->pAudioClient, shareMode, streamFlags, bufferDuration, 0, (WAVEFORMATEX*)&wf,
NULL);
8616 if (hr == E_ACCESSDENIED) {
8618 }
else if (hr == MA_AUDCLNT_E_DEVICE_IN_USE) {
8629 if (!wasInitializedUsingIAudioClient3) {
8630 hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &pData->bufferSizeInFramesOut);
8636 pData->periodSizeInFramesOut = pData->bufferSizeInFramesOut / pData->periodsOut;
8639 pData->usingAudioClient3 = wasInitializedUsingIAudioClient3;
8642 hr = ma_IAudioClient_GetService((ma_IAudioClient*)pData->pAudioClient, &MA_IID_IAudioRenderClient, (
void**)&pData->pRenderClient);
8644 hr = ma_IAudioClient_GetService((ma_IAudioClient*)pData->pAudioClient, &MA_IID_IAudioCaptureClient, (
void**)&pData->pCaptureClient);
8654 #ifdef MA_WIN32_DESKTOP
8656 ma_IPropertyStore *pProperties;
8657 hr = ma_IMMDevice_OpenPropertyStore(pDeviceInterface, STGM_READ, &pProperties);
8658 if (SUCCEEDED(hr)) {
8659 PROPVARIANT varName;
8660 ma_PropVariantInit(&varName);
8661 hr = ma_IPropertyStore_GetValue(pProperties, &MA_PKEY_Device_FriendlyName, &varName);
8662 if (SUCCEEDED(hr)) {
8663 WideCharToMultiByte(CP_UTF8, 0, varName.pwszVal, -1, pData->deviceName,
sizeof(pData->deviceName), 0, FALSE);
8664 ma_PropVariantClear(pContext, &varName);
8667 ma_IPropertyStore_Release(pProperties);
8674 #ifdef MA_WIN32_DESKTOP
8675 if (pDeviceInterface !=
NULL) {
8676 ma_IMMDevice_Release(pDeviceInterface);
8679 if (pDeviceInterface !=
NULL) {
8680 ma_IUnknown_Release(pDeviceInterface);
8685 if (pData->pRenderClient) {
8686 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pData->pRenderClient);
8687 pData->pRenderClient =
NULL;
8689 if (pData->pCaptureClient) {
8690 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pData->pCaptureClient);
8691 pData->pCaptureClient =
NULL;
8693 if (pData->pAudioClient) {
8694 ma_IAudioClient_Release((ma_IAudioClient*)pData->pAudioClient);
8695 pData->pAudioClient =
NULL;
8706 ma_device_init_internal_data__wasapi
data;
8709 ma_assert(pDevice !=
NULL);
8717 data.formatIn = pDevice->playback.format;
8718 data.channelsIn = pDevice->playback.channels;
8719 ma_copy_memory(
data.channelMapIn, pDevice->playback.channelMap,
sizeof(pDevice->playback.channelMap));
8720 data.shareMode = pDevice->playback.shareMode;
8721 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
8722 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
8723 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
8725 data.formatIn = pDevice->capture.format;
8726 data.channelsIn = pDevice->capture.channels;
8727 ma_copy_memory(
data.channelMapIn, pDevice->capture.channelMap,
sizeof(pDevice->capture.channelMap));
8728 data.shareMode = pDevice->capture.shareMode;
8729 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
8730 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
8731 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
8734 data.sampleRateIn = pDevice->sampleRate;
8735 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
8736 data.bufferSizeInFramesIn = pDevice->wasapi.originalBufferSizeInFrames;
8737 data.bufferSizeInMillisecondsIn = pDevice->wasapi.originalBufferSizeInMilliseconds;
8738 data.periodsIn = pDevice->wasapi.originalPeriods;
8739 data.noAutoConvertSRC = pDevice->wasapi.noAutoConvertSRC;
8740 data.noDefaultQualitySRC = pDevice->wasapi.noDefaultQualitySRC;
8741 result = ma_device_init_internal__wasapi(pDevice->pContext, deviceType,
NULL, &
data);
8748 if (pDevice->wasapi.pCaptureClient) {
8749 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8750 pDevice->wasapi.pCaptureClient =
NULL;
8753 if (pDevice->wasapi.pAudioClientCapture) {
8754 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8755 pDevice->wasapi.pAudioClientCapture =
NULL;
8758 pDevice->wasapi.pAudioClientCapture =
data.pAudioClient;
8759 pDevice->wasapi.pCaptureClient =
data.pCaptureClient;
8761 pDevice->capture.internalFormat =
data.formatOut;
8762 pDevice->capture.internalChannels =
data.channelsOut;
8763 pDevice->capture.internalSampleRate =
data.sampleRateOut;
8764 ma_copy_memory(pDevice->capture.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
8765 pDevice->capture.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
8766 pDevice->capture.internalPeriods =
data.periodsOut;
8767 ma_strcpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name),
data.deviceName);
8769 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
8771 pDevice->wasapi.periodSizeInFramesCapture =
data.periodSizeInFramesOut;
8772 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualBufferSizeInFramesCapture);
8775 if (pDevice->wasapi.isStartedCapture) {
8776 HRESULT hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8784 if (pDevice->wasapi.pRenderClient) {
8785 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
8786 pDevice->wasapi.pRenderClient =
NULL;
8789 if (pDevice->wasapi.pAudioClientPlayback) {
8790 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8791 pDevice->wasapi.pAudioClientPlayback =
NULL;
8794 pDevice->wasapi.pAudioClientPlayback =
data.pAudioClient;
8795 pDevice->wasapi.pRenderClient =
data.pRenderClient;
8797 pDevice->playback.internalFormat =
data.formatOut;
8798 pDevice->playback.internalChannels =
data.channelsOut;
8799 pDevice->playback.internalSampleRate =
data.sampleRateOut;
8800 ma_copy_memory(pDevice->playback.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
8801 pDevice->playback.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
8802 pDevice->playback.internalPeriods =
data.periodsOut;
8803 ma_strcpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name),
data.deviceName);
8805 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
8807 pDevice->wasapi.periodSizeInFramesPlayback =
data.periodSizeInFramesOut;
8808 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualBufferSizeInFramesPlayback);
8811 if (pDevice->wasapi.isStartedPlayback) {
8812 HRESULT hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8828 ma_assert(pContext !=
NULL);
8829 ma_assert(pDevice !=
NULL);
8831 ma_zero_object(&pDevice->wasapi);
8834 pDevice->wasapi.originalPeriods = pConfig->
periods;
8835 pDevice->wasapi.noAutoConvertSRC = pDevice->wasapi.noAutoConvertSRC;
8836 pDevice->wasapi.noDefaultQualitySRC = pDevice->wasapi.noDefaultQualitySRC;
8844 ma_device_init_internal_data__wasapi
data;
8849 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
8850 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
8851 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
8852 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
8865 pDevice->wasapi.pAudioClientCapture =
data.pAudioClient;
8866 pDevice->wasapi.pCaptureClient =
data.pCaptureClient;
8868 pDevice->capture.internalFormat =
data.formatOut;
8869 pDevice->capture.internalChannels =
data.channelsOut;
8870 pDevice->capture.internalSampleRate =
data.sampleRateOut;
8871 ma_copy_memory(pDevice->capture.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
8872 pDevice->capture.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
8873 pDevice->capture.internalPeriods =
data.periodsOut;
8874 ma_strcpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name),
data.deviceName);
8880 pDevice->wasapi.hEventCapture = CreateEventA(
NULL, FALSE, FALSE,
NULL);
8881 if (pDevice->wasapi.hEventCapture ==
NULL) {
8882 if (pDevice->wasapi.pCaptureClient !=
NULL) {
8883 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8884 pDevice->wasapi.pCaptureClient =
NULL;
8886 if (pDevice->wasapi.pAudioClientCapture !=
NULL) {
8887 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8888 pDevice->wasapi.pAudioClientCapture =
NULL;
8893 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, pDevice->wasapi.hEventCapture);
8895 pDevice->wasapi.periodSizeInFramesCapture =
data.periodSizeInFramesOut;
8896 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &pDevice->wasapi.actualBufferSizeInFramesCapture);
8900 ma_device_init_internal_data__wasapi
data;
8905 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
8906 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
8907 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
8908 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
8919 if (pDevice->wasapi.pCaptureClient !=
NULL) {
8920 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8921 pDevice->wasapi.pCaptureClient =
NULL;
8923 if (pDevice->wasapi.pAudioClientCapture !=
NULL) {
8924 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8925 pDevice->wasapi.pAudioClientCapture =
NULL;
8928 CloseHandle(pDevice->wasapi.hEventCapture);
8929 pDevice->wasapi.hEventCapture =
NULL;
8934 pDevice->wasapi.pAudioClientPlayback =
data.pAudioClient;
8935 pDevice->wasapi.pRenderClient =
data.pRenderClient;
8937 pDevice->playback.internalFormat =
data.formatOut;
8938 pDevice->playback.internalChannels =
data.channelsOut;
8939 pDevice->playback.internalSampleRate =
data.sampleRateOut;
8940 ma_copy_memory(pDevice->playback.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
8941 pDevice->playback.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
8942 pDevice->playback.internalPeriods =
data.periodsOut;
8943 ma_strcpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name),
data.deviceName);
8952 pDevice->wasapi.hEventPlayback = CreateEventA(
NULL, FALSE, TRUE,
NULL);
8953 if (pDevice->wasapi.hEventPlayback ==
NULL) {
8955 if (pDevice->wasapi.pCaptureClient !=
NULL) {
8956 ma_IAudioCaptureClient_Release((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient);
8957 pDevice->wasapi.pCaptureClient =
NULL;
8959 if (pDevice->wasapi.pAudioClientCapture !=
NULL) {
8960 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
8961 pDevice->wasapi.pAudioClientCapture =
NULL;
8964 CloseHandle(pDevice->wasapi.hEventCapture);
8965 pDevice->wasapi.hEventCapture =
NULL;
8968 if (pDevice->wasapi.pRenderClient !=
NULL) {
8969 ma_IAudioRenderClient_Release((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient);
8970 pDevice->wasapi.pRenderClient =
NULL;
8972 if (pDevice->wasapi.pAudioClientPlayback !=
NULL) {
8973 ma_IAudioClient_Release((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
8974 pDevice->wasapi.pAudioClientPlayback =
NULL;
8979 ma_IAudioClient_SetEventHandle((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, pDevice->wasapi.hEventPlayback);
8981 pDevice->wasapi.periodSizeInFramesPlayback =
data.periodSizeInFramesOut;
8982 ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &pDevice->wasapi.actualBufferSizeInFramesPlayback);
8989 #ifdef MA_WIN32_DESKTOP
8991 ma_IMMDeviceEnumerator* pDeviceEnumerator;
8992 HRESULT hr = ma_CoCreateInstance(pContext, MA_CLSID_MMDeviceEnumerator,
NULL, CLSCTX_ALL, MA_IID_IMMDeviceEnumerator, (
void**)&pDeviceEnumerator);
8994 ma_device_uninit__wasapi(pDevice);
8998 pDevice->wasapi.notificationClient.lpVtbl = (
void*)&g_maNotificationCientVtbl;
8999 pDevice->wasapi.notificationClient.counter = 1;
9000 pDevice->wasapi.notificationClient.pDevice = pDevice;
9002 hr = pDeviceEnumerator->lpVtbl->RegisterEndpointNotificationCallback(pDeviceEnumerator, &pDevice->wasapi.notificationClient);
9003 if (SUCCEEDED(hr)) {
9004 pDevice->wasapi.pDeviceEnumerator = (
ma_ptr)pDeviceEnumerator;
9007 ma_IMMDeviceEnumerator_Release(pDeviceEnumerator);
9012 ma_atomic_exchange_32(&pDevice->wasapi.isStartedCapture,
MA_FALSE);
9013 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_FALSE);
9024 ma_assert(pDevice !=
NULL);
9025 ma_assert(pFrameCount !=
NULL);
9029 if ((
ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientPlayback && (
ma_ptr)pAudioClient != pDevice->wasapi.pAudioClientCapture) {
9033 hr = ma_IAudioClient_GetCurrentPadding(pAudioClient, &paddingFramesCount);
9039 shareMode = ((
ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) ? pDevice->playback.shareMode : pDevice->capture.shareMode;
9041 *pFrameCount = paddingFramesCount;
9043 if ((
ma_ptr)pAudioClient == pDevice->wasapi.pAudioClientPlayback) {
9044 *pFrameCount = pDevice->wasapi.actualBufferSizeInFramesPlayback - paddingFramesCount;
9046 *pFrameCount = paddingFramesCount;
9055 ma_assert(pDevice !=
NULL);
9058 return pDevice->wasapi.hasDefaultPlaybackDeviceChanged;
9062 return pDevice->wasapi.hasDefaultCaptureDeviceChanged;
9077 ma_atomic_exchange_32(&pDevice->wasapi.hasDefaultPlaybackDeviceChanged,
MA_FALSE);
9080 ma_atomic_exchange_32(&pDevice->wasapi.hasDefaultCaptureDeviceChanged,
MA_FALSE);
9084 #ifdef MA_DEBUG_OUTPUT
9085 printf(
"=== CHANGING DEVICE ===\n");
9088 result = ma_device_reinit__wasapi(pDevice, deviceType);
9093 ma_device__post_init_setup(pDevice, deviceType);
9101 ma_assert(pDevice !=
NULL);
9108 SetEvent((HANDLE)pDevice->wasapi.hEventCapture);
9120 ma_uint32 framesWrittenToPlaybackDevice = 0;
9121 ma_uint32 mappedBufferSizeInFramesCapture = 0;
9122 ma_uint32 mappedBufferSizeInFramesPlayback = 0;
9123 ma_uint32 mappedBufferFramesRemainingCapture = 0;
9124 ma_uint32 mappedBufferFramesRemainingPlayback = 0;
9125 BYTE* pMappedBufferCapture =
NULL;
9126 BYTE* pMappedBufferPlayback =
NULL;
9127 ma_uint32 bpfCapture = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
9128 ma_uint32 bpfPlayback = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
9129 ma_uint8 inputDataInExternalFormat[4096];
9130 ma_uint32 inputDataInExternalFormatCap =
sizeof(inputDataInExternalFormat) / bpfCapture;
9131 ma_uint8 outputDataInExternalFormat[4096];
9132 ma_uint32 outputDataInExternalFormatCap =
sizeof(outputDataInExternalFormat) / bpfPlayback;
9133 ma_uint32 periodSizeInFramesCapture = 0;
9135 ma_assert(pDevice !=
NULL);
9139 periodSizeInFramesCapture = (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods);
9141 hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9145 ma_atomic_exchange_32(&pDevice->wasapi.isStartedCapture,
MA_TRUE);
9148 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
9165 switch (pDevice->type)
9174 if (pMappedBufferPlayback ==
NULL) {
9177 if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) == WAIT_FAILED) {
9182 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
9192 if (framesAvailablePlayback > pDevice->wasapi.periodSizeInFramesPlayback) {
9193 framesAvailablePlayback = pDevice->wasapi.periodSizeInFramesPlayback;
9198 if (framesAvailablePlayback == 0) {
9201 if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) == WAIT_FAILED) {
9210 hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedBufferPlayback);
9217 mappedBufferSizeInFramesPlayback = framesAvailablePlayback;
9218 mappedBufferFramesRemainingPlayback = framesAvailablePlayback;
9224 if (pMappedBufferCapture ==
NULL) {
9226 if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) == WAIT_FAILED) {
9231 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
9240 if (framesAvailableCapture == 0) {
9243 if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) == WAIT_FAILED) {
9252 mappedBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
9253 hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedBufferCapture, &mappedBufferSizeInFramesCapture, &flagsCapture,
NULL,
NULL);
9262 if ((flagsCapture & MA_AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY) != 0) {
9264 #ifdef MA_DEBUG_OUTPUT
9265 printf(
"[WASAPI] Data discontinuity (possible overrun). framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedBufferSizeInFramesCapture);
9273 if (framesAvailableCapture >= pDevice->wasapi.actualBufferSizeInFramesCapture ) {
9274 #ifdef MA_DEBUG_OUTPUT
9275 printf(
"[WASAPI] Synchronizing capture stream. ");
9279 hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedBufferSizeInFramesCapture);
9284 framesAvailableCapture -= mappedBufferSizeInFramesCapture;
9286 if (framesAvailableCapture > 0) {
9287 mappedBufferSizeInFramesCapture = ma_min(framesAvailableCapture, periodSizeInFramesCapture);
9288 hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedBufferCapture, &mappedBufferSizeInFramesCapture, &flagsCapture,
NULL,
NULL);
9295 pMappedBufferCapture =
NULL;
9296 mappedBufferSizeInFramesCapture = 0;
9298 }
while (framesAvailableCapture > periodSizeInFramesCapture);
9299 #ifdef MA_DEBUG_OUTPUT
9300 printf(
"framesAvailableCapture=%d, mappedBufferSizeInFramesCapture=%d\n", framesAvailableCapture, mappedBufferSizeInFramesCapture);
9304 #ifdef MA_DEBUG_OUTPUT
9305 if (flagsCapture != 0) {
9306 printf(
"[WASAPI] Capture Flags: %d\n", flagsCapture);
9311 mappedBufferFramesRemainingCapture = mappedBufferSizeInFramesCapture;
9313 pDevice->capture._dspFrameCount = mappedBufferSizeInFramesCapture;
9314 if ((flagsCapture & MA_AUDCLNT_BUFFERFLAGS_SILENT) == 0) {
9315 pDevice->capture._dspFrames = (
const ma_uint8*)pMappedBufferCapture;
9317 pDevice->capture._dspFrames =
NULL;
9324 BYTE* pRunningBufferCapture;
9325 BYTE* pRunningBufferPlayback;
9329 pRunningBufferCapture = pMappedBufferCapture + ((mappedBufferSizeInFramesCapture - mappedBufferFramesRemainingCapture ) * bpfPlayback);
9330 pRunningBufferPlayback = pMappedBufferPlayback + ((mappedBufferSizeInFramesPlayback - mappedBufferFramesRemainingPlayback) * bpfPlayback);
9333 if (!pDevice->playback.converter.isPassthrough) {
9335 if (framesProcessed > 0) {
9336 mappedBufferFramesRemainingPlayback -= framesProcessed;
9337 if (mappedBufferFramesRemainingPlayback == 0) {
9347 if (pDevice->capture.converter.isPassthrough && pDevice->playback.converter.isPassthrough) {
9349 framesToProcess = ma_min(mappedBufferFramesRemainingCapture, mappedBufferFramesRemainingPlayback);
9350 framesProcessed = framesToProcess;
9352 ma_device__on_data(pDevice, pRunningBufferPlayback, pRunningBufferCapture, framesToProcess);
9354 mappedBufferFramesRemainingCapture -= framesProcessed;
9355 mappedBufferFramesRemainingPlayback -= framesProcessed;
9357 if (mappedBufferFramesRemainingCapture == 0) {
9360 if (mappedBufferFramesRemainingPlayback == 0) {
9363 }
else if (pDevice->capture.converter.isPassthrough) {
9365 framesToProcess = ma_min(mappedBufferFramesRemainingCapture, outputDataInExternalFormatCap);
9366 framesProcessed = framesToProcess;
9368 ma_device__on_data(pDevice, outputDataInExternalFormat, pRunningBufferCapture, framesToProcess);
9369 mappedBufferFramesRemainingCapture -= framesProcessed;
9371 pDevice->playback._dspFrameCount = framesProcessed;
9372 pDevice->playback._dspFrames = (
const ma_uint8*)outputDataInExternalFormat;
9374 if (mappedBufferFramesRemainingCapture == 0) {
9377 }
else if (pDevice->playback.converter.isPassthrough) {
9379 framesToProcess = ma_min(inputDataInExternalFormatCap, mappedBufferFramesRemainingPlayback);
9381 if (framesProcessed == 0) {
9383 mappedBufferFramesRemainingCapture = 0;
9387 ma_device__on_data(pDevice, pRunningBufferPlayback, inputDataInExternalFormat, framesProcessed);
9388 mappedBufferFramesRemainingPlayback -= framesProcessed;
9390 if (framesProcessed < framesToProcess) {
9391 mappedBufferFramesRemainingCapture = 0;
9395 if (mappedBufferFramesRemainingPlayback == 0) {
9399 framesToProcess = ma_min(inputDataInExternalFormatCap, outputDataInExternalFormatCap);
9401 if (framesProcessed == 0) {
9403 mappedBufferFramesRemainingCapture = 0;
9407 ma_device__on_data(pDevice, outputDataInExternalFormat, inputDataInExternalFormat, framesProcessed);
9409 pDevice->playback._dspFrameCount = framesProcessed;
9410 pDevice->playback._dspFrames = (
const ma_uint8*)outputDataInExternalFormat;
9412 if (framesProcessed < framesToProcess) {
9414 mappedBufferFramesRemainingCapture = 0;
9422 if (mappedBufferFramesRemainingCapture == 0 && pMappedBufferCapture !=
NULL) {
9423 hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedBufferSizeInFramesCapture);
9432 pMappedBufferCapture =
NULL;
9433 mappedBufferFramesRemainingCapture = 0;
9434 mappedBufferSizeInFramesCapture = 0;
9438 if (mappedBufferFramesRemainingPlayback == 0) {
9445 if (mappedBufferFramesRemainingPlayback == 0 && pMappedBufferPlayback !=
NULL) {
9446 hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedBufferSizeInFramesPlayback, 0);
9454 framesWrittenToPlaybackDevice += mappedBufferSizeInFramesPlayback;
9456 pMappedBufferPlayback =
NULL;
9457 mappedBufferFramesRemainingPlayback = 0;
9458 mappedBufferSizeInFramesPlayback = 0;
9461 if (!pDevice->wasapi.isStartedPlayback) {
9462 ma_uint32 startThreshold = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods * 1;
9465 if (startThreshold > pDevice->wasapi.actualBufferSizeInFramesPlayback) {
9466 startThreshold = pDevice->wasapi.actualBufferSizeInFramesPlayback;
9469 if (pDevice->playback.shareMode ==
ma_share_mode_exclusive || framesWrittenToPlaybackDevice >= startThreshold) {
9470 hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9472 ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9473 ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9476 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_TRUE);
9490 if (WaitForSingleObject(pDevice->wasapi.hEventCapture, INFINITE) == WAIT_FAILED) {
9496 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture, &framesAvailableCapture);
9502 if (framesAvailableCapture < pDevice->wasapi.periodSizeInFramesCapture) {
9507 mappedBufferSizeInFramesCapture = framesAvailableCapture;
9508 hr = ma_IAudioCaptureClient_GetBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, (BYTE**)&pMappedBufferCapture, &mappedBufferSizeInFramesCapture, &flagsCapture,
NULL,
NULL);
9516 ma_device__send_frames_to_client(pDevice, mappedBufferSizeInFramesCapture, pMappedBufferCapture);
9519 hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedBufferSizeInFramesCapture);
9520 pMappedBufferCapture =
NULL;
9521 mappedBufferSizeInFramesCapture = 0;
9536 if (WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE) == WAIT_FAILED) {
9542 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
9548 if (framesAvailablePlayback < pDevice->wasapi.periodSizeInFramesPlayback) {
9553 hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, &pMappedBufferPlayback);
9561 ma_device__read_frames_from_client(pDevice, framesAvailablePlayback, pMappedBufferPlayback);
9564 hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, framesAvailablePlayback, 0);
9565 pMappedBufferPlayback =
NULL;
9566 mappedBufferSizeInFramesPlayback = 0;
9574 framesWrittenToPlaybackDevice += framesAvailablePlayback;
9575 if (!pDevice->wasapi.isStartedPlayback) {
9576 if (pDevice->playback.shareMode ==
ma_share_mode_exclusive || framesWrittenToPlaybackDevice >= (pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*1) {
9577 hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9583 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_TRUE);
9595 if (pMappedBufferCapture !=
NULL) {
9596 hr = ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, mappedBufferSizeInFramesCapture);
9599 hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9605 hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture);
9610 ma_atomic_exchange_32(&pDevice->wasapi.isStartedCapture,
MA_FALSE);
9615 if (pMappedBufferPlayback !=
NULL) {
9616 hr = ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, mappedBufferSizeInFramesPlayback, 0);
9623 if (pDevice->wasapi.isStartedPlayback) {
9625 WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE);
9630 result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback);
9635 if (framesAvailablePlayback >= pDevice->wasapi.actualBufferSizeInFramesPlayback) {
9643 if (framesAvailablePlayback == prevFramesAvaialablePlayback) {
9646 prevFramesAvaialablePlayback = framesAvailablePlayback;
9648 WaitForSingleObject(pDevice->wasapi.hEventPlayback, INFINITE);
9649 ResetEvent(pDevice->wasapi.hEventPlayback);
9654 hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9660 hr = ma_IAudioClient_Reset((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback);
9665 ma_atomic_exchange_32(&pDevice->wasapi.isStartedPlayback,
MA_FALSE);
9673 ma_assert(pContext !=
NULL);
9684 ma_assert(pContext !=
NULL);
9688 #ifdef MA_WIN32_DESKTOP
9696 ma_OSVERSIONINFOEXW osvi;
9698 ma_PFNVerifyVersionInfoW _VerifyVersionInfoW;
9699 ma_PFNVerSetConditionMask _VerSetConditionMask;
9701 kernel32DLL = ma_dlopen(pContext,
"kernel32.dll");
9702 if (kernel32DLL ==
NULL) {
9706 _VerifyVersionInfoW = (ma_PFNVerifyVersionInfoW)ma_dlsym(pContext, kernel32DLL,
"VerifyVersionInfoW");
9707 _VerSetConditionMask = (ma_PFNVerSetConditionMask)ma_dlsym(pContext, kernel32DLL,
"VerSetConditionMask");
9708 if (_VerifyVersionInfoW ==
NULL || _VerSetConditionMask ==
NULL) {
9709 ma_dlclose(pContext, kernel32DLL);
9713 ma_zero_object(&osvi);
9714 osvi.dwOSVersionInfoSize =
sizeof(osvi);
9715 osvi.dwMajorVersion = HIBYTE(MA_WIN32_WINNT_VISTA);
9716 osvi.dwMinorVersion = LOBYTE(MA_WIN32_WINNT_VISTA);
9717 osvi.wServicePackMajor = 1;
9718 if (_VerifyVersionInfoW(&osvi, MA_VER_MAJORVERSION | MA_VER_MINORVERSION | MA_VER_SERVICEPACKMAJOR, _VerSetConditionMask(_VerSetConditionMask(_VerSetConditionMask(0, MA_VER_MAJORVERSION, MA_VER_GREATER_EQUAL), MA_VER_MINORVERSION, MA_VER_GREATER_EQUAL), MA_VER_SERVICEPACKMAJOR, MA_VER_GREATER_EQUAL))) {
9724 ma_dlclose(pContext, kernel32DLL);
9732 pContext->
onUninit = ma_context_uninit__wasapi;
9734 pContext->
onEnumDevices = ma_context_enumerate_devices__wasapi;
9751 #ifdef MA_HAS_DSOUND
9754 GUID MA_GUID_IID_DirectSoundNotify = {0xb0210783, 0x89cd, 0x11d0, {0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16}};
9757 #define MA_DSSCL_NORMAL 1
9758 #define MA_DSSCL_PRIORITY 2
9759 #define MA_DSSCL_EXCLUSIVE 3
9760 #define MA_DSSCL_WRITEPRIMARY 4
9762 #define MA_DSCAPS_PRIMARYMONO 0x00000001
9763 #define MA_DSCAPS_PRIMARYSTEREO 0x00000002
9764 #define MA_DSCAPS_PRIMARY8BIT 0x00000004
9765 #define MA_DSCAPS_PRIMARY16BIT 0x00000008
9766 #define MA_DSCAPS_CONTINUOUSRATE 0x00000010
9767 #define MA_DSCAPS_EMULDRIVER 0x00000020
9768 #define MA_DSCAPS_CERTIFIED 0x00000040
9769 #define MA_DSCAPS_SECONDARYMONO 0x00000100
9770 #define MA_DSCAPS_SECONDARYSTEREO 0x00000200
9771 #define MA_DSCAPS_SECONDARY8BIT 0x00000400
9772 #define MA_DSCAPS_SECONDARY16BIT 0x00000800
9774 #define MA_DSBCAPS_PRIMARYBUFFER 0x00000001
9775 #define MA_DSBCAPS_STATIC 0x00000002
9776 #define MA_DSBCAPS_LOCHARDWARE 0x00000004
9777 #define MA_DSBCAPS_LOCSOFTWARE 0x00000008
9778 #define MA_DSBCAPS_CTRL3D 0x00000010
9779 #define MA_DSBCAPS_CTRLFREQUENCY 0x00000020
9780 #define MA_DSBCAPS_CTRLPAN 0x00000040
9781 #define MA_DSBCAPS_CTRLVOLUME 0x00000080
9782 #define MA_DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100
9783 #define MA_DSBCAPS_CTRLFX 0x00000200
9784 #define MA_DSBCAPS_STICKYFOCUS 0x00004000
9785 #define MA_DSBCAPS_GLOBALFOCUS 0x00008000
9786 #define MA_DSBCAPS_GETCURRENTPOSITION2 0x00010000
9787 #define MA_DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000
9788 #define MA_DSBCAPS_LOCDEFER 0x00040000
9789 #define MA_DSBCAPS_TRUEPLAYPOSITION 0x00080000
9791 #define MA_DSBPLAY_LOOPING 0x00000001
9792 #define MA_DSBPLAY_LOCHARDWARE 0x00000002
9793 #define MA_DSBPLAY_LOCSOFTWARE 0x00000004
9794 #define MA_DSBPLAY_TERMINATEBY_TIME 0x00000008
9795 #define MA_DSBPLAY_TERMINATEBY_DISTANCE 0x00000010
9796 #define MA_DSBPLAY_TERMINATEBY_PRIORITY 0x00000020
9798 #define MA_DSCBSTART_LOOPING 0x00000001
9804 DWORD dwBufferBytes;
9806 WAVEFORMATEX* lpwfxFormat;
9807 GUID guid3DAlgorithm;
9814 DWORD dwBufferBytes;
9816 WAVEFORMATEX* lpwfxFormat;
9825 DWORD dwMinSecondarySampleRate;
9826 DWORD dwMaxSecondarySampleRate;
9827 DWORD dwPrimaryBuffers;
9828 DWORD dwMaxHwMixingAllBuffers;
9829 DWORD dwMaxHwMixingStaticBuffers;
9830 DWORD dwMaxHwMixingStreamingBuffers;
9831 DWORD dwFreeHwMixingAllBuffers;
9832 DWORD dwFreeHwMixingStaticBuffers;
9833 DWORD dwFreeHwMixingStreamingBuffers;
9834 DWORD dwMaxHw3DAllBuffers;
9835 DWORD dwMaxHw3DStaticBuffers;
9836 DWORD dwMaxHw3DStreamingBuffers;
9837 DWORD dwFreeHw3DAllBuffers;
9838 DWORD dwFreeHw3DStaticBuffers;
9839 DWORD dwFreeHw3DStreamingBuffers;
9840 DWORD dwTotalHwMemBytes;
9841 DWORD dwFreeHwMemBytes;
9842 DWORD dwMaxContigFreeHwMemBytes;
9843 DWORD dwUnlockTransferRateHwBuffers;
9844 DWORD dwPlayCpuOverheadSwBuffers;
9853 DWORD dwBufferBytes;
9854 DWORD dwUnlockTransferRate;
9855 DWORD dwPlayCpuOverhead;
9870 DWORD dwBufferBytes;
9877 HANDLE hEventNotify;
9878 } MA_DSBPOSITIONNOTIFY;
9880 typedef struct ma_IDirectSound ma_IDirectSound;
9881 typedef struct ma_IDirectSoundBuffer ma_IDirectSoundBuffer;
9882 typedef struct ma_IDirectSoundCapture ma_IDirectSoundCapture;
9883 typedef struct ma_IDirectSoundCaptureBuffer ma_IDirectSoundCaptureBuffer;
9884 typedef struct ma_IDirectSoundNotify ma_IDirectSoundNotify;
9898 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSound* pThis,
const IID*
const riid,
void** ppObject);
9899 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSound* pThis);
9900 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSound* pThis);
9903 HRESULT (STDMETHODCALLTYPE * CreateSoundBuffer) (ma_IDirectSound* pThis,
const MA_DSBUFFERDESC* pDSBufferDesc, ma_IDirectSoundBuffer** ppDSBuffer,
void* pUnkOuter);
9904 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps);
9905 HRESULT (STDMETHODCALLTYPE * DuplicateSoundBuffer)(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate);
9906 HRESULT (STDMETHODCALLTYPE * SetCooperativeLevel) (ma_IDirectSound* pThis, HWND hwnd, DWORD dwLevel);
9907 HRESULT (STDMETHODCALLTYPE * Compact) (ma_IDirectSound* pThis);
9908 HRESULT (STDMETHODCALLTYPE * GetSpeakerConfig) (ma_IDirectSound* pThis, DWORD* pSpeakerConfig);
9909 HRESULT (STDMETHODCALLTYPE * SetSpeakerConfig) (ma_IDirectSound* pThis, DWORD dwSpeakerConfig);
9910 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSound* pThis,
const GUID* pGuidDevice);
9911 } ma_IDirectSoundVtbl;
9912 struct ma_IDirectSound
9914 ma_IDirectSoundVtbl* lpVtbl;
9916 HRESULT ma_IDirectSound_QueryInterface(ma_IDirectSound* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
9917 ULONG ma_IDirectSound_AddRef(ma_IDirectSound* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
9918 ULONG ma_IDirectSound_Release(ma_IDirectSound* pThis) {
return pThis->lpVtbl->Release(pThis); }
9919 HRESULT ma_IDirectSound_CreateSoundBuffer(ma_IDirectSound* pThis,
const MA_DSBUFFERDESC* pDSBufferDesc, ma_IDirectSoundBuffer** ppDSBuffer,
void* pUnkOuter) {
return pThis->lpVtbl->CreateSoundBuffer(pThis, pDSBufferDesc, ppDSBuffer, pUnkOuter); }
9920 HRESULT ma_IDirectSound_GetCaps(ma_IDirectSound* pThis, MA_DSCAPS* pDSCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSCaps); }
9921 HRESULT ma_IDirectSound_DuplicateSoundBuffer(ma_IDirectSound* pThis, ma_IDirectSoundBuffer* pDSBufferOriginal, ma_IDirectSoundBuffer** ppDSBufferDuplicate) {
return pThis->lpVtbl->DuplicateSoundBuffer(pThis, pDSBufferOriginal, ppDSBufferDuplicate); }
9922 HRESULT ma_IDirectSound_SetCooperativeLevel(ma_IDirectSound* pThis, HWND hwnd, DWORD dwLevel) {
return pThis->lpVtbl->SetCooperativeLevel(pThis, hwnd, dwLevel); }
9923 HRESULT ma_IDirectSound_Compact(ma_IDirectSound* pThis) {
return pThis->lpVtbl->Compact(pThis); }
9924 HRESULT ma_IDirectSound_GetSpeakerConfig(ma_IDirectSound* pThis, DWORD* pSpeakerConfig) {
return pThis->lpVtbl->GetSpeakerConfig(pThis, pSpeakerConfig); }
9925 HRESULT ma_IDirectSound_SetSpeakerConfig(ma_IDirectSound* pThis, DWORD dwSpeakerConfig) {
return pThis->lpVtbl->SetSpeakerConfig(pThis, dwSpeakerConfig); }
9926 HRESULT ma_IDirectSound_Initialize(ma_IDirectSound* pThis,
const GUID* pGuidDevice) {
return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
9933 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundBuffer* pThis,
const IID*
const riid,
void** ppObject);
9934 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundBuffer* pThis);
9935 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundBuffer* pThis);
9938 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps);
9939 HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundBuffer* pThis, DWORD* pCurrentPlayCursor, DWORD* pCurrentWriteCursor);
9940 HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten);
9941 HRESULT (STDMETHODCALLTYPE * GetVolume) (ma_IDirectSoundBuffer* pThis, LONG* pVolume);
9942 HRESULT (STDMETHODCALLTYPE * GetPan) (ma_IDirectSoundBuffer* pThis, LONG* pPan);
9943 HRESULT (STDMETHODCALLTYPE * GetFrequency) (ma_IDirectSoundBuffer* pThis, DWORD* pFrequency);
9944 HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundBuffer* pThis, DWORD* pStatus);
9945 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound,
const MA_DSBUFFERDESC* pDSBufferDesc);
9946 HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundBuffer* pThis, DWORD dwOffset, DWORD dwBytes,
void** ppAudioPtr1, DWORD* pAudioBytes1,
void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags);
9947 HRESULT (STDMETHODCALLTYPE * Play) (ma_IDirectSoundBuffer* pThis, DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags);
9948 HRESULT (STDMETHODCALLTYPE * SetCurrentPosition)(ma_IDirectSoundBuffer* pThis, DWORD dwNewPosition);
9949 HRESULT (STDMETHODCALLTYPE * SetFormat) (ma_IDirectSoundBuffer* pThis,
const WAVEFORMATEX* pFormat);
9950 HRESULT (STDMETHODCALLTYPE * SetVolume) (ma_IDirectSoundBuffer* pThis, LONG volume);
9951 HRESULT (STDMETHODCALLTYPE * SetPan) (ma_IDirectSoundBuffer* pThis, LONG pan);
9952 HRESULT (STDMETHODCALLTYPE * SetFrequency) (ma_IDirectSoundBuffer* pThis, DWORD dwFrequency);
9953 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundBuffer* pThis);
9954 HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundBuffer* pThis,
void* pAudioPtr1, DWORD dwAudioBytes1,
void* pAudioPtr2, DWORD dwAudioBytes2);
9955 HRESULT (STDMETHODCALLTYPE * Restore) (ma_IDirectSoundBuffer* pThis);
9956 } ma_IDirectSoundBufferVtbl;
9957 struct ma_IDirectSoundBuffer
9959 ma_IDirectSoundBufferVtbl* lpVtbl;
9961 HRESULT ma_IDirectSoundBuffer_QueryInterface(ma_IDirectSoundBuffer* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
9962 ULONG ma_IDirectSoundBuffer_AddRef(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
9963 ULONG ma_IDirectSoundBuffer_Release(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->Release(pThis); }
9964 HRESULT ma_IDirectSoundBuffer_GetCaps(ma_IDirectSoundBuffer* pThis, MA_DSBCAPS* pDSBufferCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSBufferCaps); }
9965 HRESULT ma_IDirectSoundBuffer_GetCurrentPosition(ma_IDirectSoundBuffer* pThis, DWORD* pCurrentPlayCursor, DWORD* pCurrentWriteCursor) {
return pThis->lpVtbl->GetCurrentPosition(pThis, pCurrentPlayCursor, pCurrentWriteCursor); }
9966 HRESULT ma_IDirectSoundBuffer_GetFormat(ma_IDirectSoundBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten) {
return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
9967 HRESULT ma_IDirectSoundBuffer_GetVolume(ma_IDirectSoundBuffer* pThis, LONG* pVolume) {
return pThis->lpVtbl->GetVolume(pThis, pVolume); }
9968 HRESULT ma_IDirectSoundBuffer_GetPan(ma_IDirectSoundBuffer* pThis, LONG* pPan) {
return pThis->lpVtbl->GetPan(pThis, pPan); }
9969 HRESULT ma_IDirectSoundBuffer_GetFrequency(ma_IDirectSoundBuffer* pThis, DWORD* pFrequency) {
return pThis->lpVtbl->GetFrequency(pThis, pFrequency); }
9970 HRESULT ma_IDirectSoundBuffer_GetStatus(ma_IDirectSoundBuffer* pThis, DWORD* pStatus) {
return pThis->lpVtbl->GetStatus(pThis, pStatus); }
9971 HRESULT ma_IDirectSoundBuffer_Initialize(ma_IDirectSoundBuffer* pThis, ma_IDirectSound* pDirectSound,
const MA_DSBUFFERDESC* pDSBufferDesc) {
return pThis->lpVtbl->Initialize(pThis, pDirectSound, pDSBufferDesc); }
9972 HRESULT ma_IDirectSoundBuffer_Lock(ma_IDirectSoundBuffer* pThis, DWORD dwOffset, DWORD dwBytes,
void** ppAudioPtr1, DWORD* pAudioBytes1,
void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags) {
return pThis->lpVtbl->Lock(pThis, dwOffset, dwBytes, ppAudioPtr1, pAudioBytes1, ppAudioPtr2, pAudioBytes2, dwFlags); }
9973 HRESULT ma_IDirectSoundBuffer_Play(ma_IDirectSoundBuffer* pThis, DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) {
return pThis->lpVtbl->Play(pThis, dwReserved1, dwPriority, dwFlags); }
9974 HRESULT ma_IDirectSoundBuffer_SetCurrentPosition(ma_IDirectSoundBuffer* pThis, DWORD dwNewPosition) {
return pThis->lpVtbl->SetCurrentPosition(pThis, dwNewPosition); }
9975 HRESULT ma_IDirectSoundBuffer_SetFormat(ma_IDirectSoundBuffer* pThis,
const WAVEFORMATEX* pFormat) {
return pThis->lpVtbl->SetFormat(pThis, pFormat); }
9976 HRESULT ma_IDirectSoundBuffer_SetVolume(ma_IDirectSoundBuffer* pThis, LONG volume) {
return pThis->lpVtbl->SetVolume(pThis, volume); }
9977 HRESULT ma_IDirectSoundBuffer_SetPan(ma_IDirectSoundBuffer* pThis, LONG pan) {
return pThis->lpVtbl->SetPan(pThis, pan); }
9978 HRESULT ma_IDirectSoundBuffer_SetFrequency(ma_IDirectSoundBuffer* pThis, DWORD dwFrequency) {
return pThis->lpVtbl->SetFrequency(pThis, dwFrequency); }
9979 HRESULT ma_IDirectSoundBuffer_Stop(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->Stop(pThis); }
9980 HRESULT ma_IDirectSoundBuffer_Unlock(ma_IDirectSoundBuffer* pThis,
void* pAudioPtr1, DWORD dwAudioBytes1,
void* pAudioPtr2, DWORD dwAudioBytes2) {
return pThis->lpVtbl->Unlock(pThis, pAudioPtr1, dwAudioBytes1, pAudioPtr2, dwAudioBytes2); }
9981 HRESULT ma_IDirectSoundBuffer_Restore(ma_IDirectSoundBuffer* pThis) {
return pThis->lpVtbl->Restore(pThis); }
9988 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCapture* pThis,
const IID*
const riid,
void** ppObject);
9989 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCapture* pThis);
9990 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCapture* pThis);
9993 HRESULT (STDMETHODCALLTYPE * CreateCaptureBuffer)(ma_IDirectSoundCapture* pThis,
const MA_DSCBUFFERDESC* pDSCBufferDesc, ma_IDirectSoundCaptureBuffer** ppDSCBuffer,
void* pUnkOuter);
9994 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps);
9995 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCapture* pThis,
const GUID* pGuidDevice);
9996 } ma_IDirectSoundCaptureVtbl;
9997 struct ma_IDirectSoundCapture
9999 ma_IDirectSoundCaptureVtbl* lpVtbl;
10001 HRESULT ma_IDirectSoundCapture_QueryInterface(ma_IDirectSoundCapture* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10002 ULONG ma_IDirectSoundCapture_AddRef(ma_IDirectSoundCapture* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
10003 ULONG ma_IDirectSoundCapture_Release(ma_IDirectSoundCapture* pThis) {
return pThis->lpVtbl->Release(pThis); }
10004 HRESULT ma_IDirectSoundCapture_CreateCaptureBuffer(ma_IDirectSoundCapture* pThis,
const MA_DSCBUFFERDESC* pDSCBufferDesc, ma_IDirectSoundCaptureBuffer** ppDSCBuffer,
void* pUnkOuter) {
return pThis->lpVtbl->CreateCaptureBuffer(pThis, pDSCBufferDesc, ppDSCBuffer, pUnkOuter); }
10005 HRESULT ma_IDirectSoundCapture_GetCaps (ma_IDirectSoundCapture* pThis, MA_DSCCAPS* pDSCCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSCCaps); }
10006 HRESULT ma_IDirectSoundCapture_Initialize (ma_IDirectSoundCapture* pThis,
const GUID* pGuidDevice) {
return pThis->lpVtbl->Initialize(pThis, pGuidDevice); }
10013 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundCaptureBuffer* pThis,
const IID*
const riid,
void** ppObject);
10014 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundCaptureBuffer* pThis);
10015 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundCaptureBuffer* pThis);
10018 HRESULT (STDMETHODCALLTYPE * GetCaps) (ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps);
10019 HRESULT (STDMETHODCALLTYPE * GetCurrentPosition)(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pCapturePosition, DWORD* pReadPosition);
10020 HRESULT (STDMETHODCALLTYPE * GetFormat) (ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten);
10021 HRESULT (STDMETHODCALLTYPE * GetStatus) (ma_IDirectSoundCaptureBuffer* pThis, DWORD* pStatus);
10022 HRESULT (STDMETHODCALLTYPE * Initialize) (ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture,
const MA_DSCBUFFERDESC* pDSCBufferDesc);
10023 HRESULT (STDMETHODCALLTYPE * Lock) (ma_IDirectSoundCaptureBuffer* pThis, DWORD dwOffset, DWORD dwBytes,
void** ppAudioPtr1, DWORD* pAudioBytes1,
void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags);
10024 HRESULT (STDMETHODCALLTYPE * Start) (ma_IDirectSoundCaptureBuffer* pThis, DWORD dwFlags);
10025 HRESULT (STDMETHODCALLTYPE * Stop) (ma_IDirectSoundCaptureBuffer* pThis);
10026 HRESULT (STDMETHODCALLTYPE * Unlock) (ma_IDirectSoundCaptureBuffer* pThis,
void* pAudioPtr1, DWORD dwAudioBytes1,
void* pAudioPtr2, DWORD dwAudioBytes2);
10027 } ma_IDirectSoundCaptureBufferVtbl;
10028 struct ma_IDirectSoundCaptureBuffer
10030 ma_IDirectSoundCaptureBufferVtbl* lpVtbl;
10032 HRESULT ma_IDirectSoundCaptureBuffer_QueryInterface(ma_IDirectSoundCaptureBuffer* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10033 ULONG ma_IDirectSoundCaptureBuffer_AddRef(ma_IDirectSoundCaptureBuffer* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
10034 ULONG ma_IDirectSoundCaptureBuffer_Release(ma_IDirectSoundCaptureBuffer* pThis) {
return pThis->lpVtbl->Release(pThis); }
10035 HRESULT ma_IDirectSoundCaptureBuffer_GetCaps(ma_IDirectSoundCaptureBuffer* pThis, MA_DSCBCAPS* pDSCBCaps) {
return pThis->lpVtbl->GetCaps(pThis, pDSCBCaps); }
10036 HRESULT ma_IDirectSoundCaptureBuffer_GetCurrentPosition(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pCapturePosition, DWORD* pReadPosition) {
return pThis->lpVtbl->GetCurrentPosition(pThis, pCapturePosition, pReadPosition); }
10037 HRESULT ma_IDirectSoundCaptureBuffer_GetFormat(ma_IDirectSoundCaptureBuffer* pThis, WAVEFORMATEX* pFormat, DWORD dwSizeAllocated, DWORD* pSizeWritten) {
return pThis->lpVtbl->GetFormat(pThis, pFormat, dwSizeAllocated, pSizeWritten); }
10038 HRESULT ma_IDirectSoundCaptureBuffer_GetStatus(ma_IDirectSoundCaptureBuffer* pThis, DWORD* pStatus) {
return pThis->lpVtbl->GetStatus(pThis, pStatus); }
10039 HRESULT ma_IDirectSoundCaptureBuffer_Initialize(ma_IDirectSoundCaptureBuffer* pThis, ma_IDirectSoundCapture* pDirectSoundCapture,
const MA_DSCBUFFERDESC* pDSCBufferDesc) {
return pThis->lpVtbl->Initialize(pThis, pDirectSoundCapture, pDSCBufferDesc); }
10040 HRESULT ma_IDirectSoundCaptureBuffer_Lock(ma_IDirectSoundCaptureBuffer* pThis, DWORD dwOffset, DWORD dwBytes,
void** ppAudioPtr1, DWORD* pAudioBytes1,
void** ppAudioPtr2, DWORD* pAudioBytes2, DWORD dwFlags) {
return pThis->lpVtbl->Lock(pThis, dwOffset, dwBytes, ppAudioPtr1, pAudioBytes1, ppAudioPtr2, pAudioBytes2, dwFlags); }
10041 HRESULT ma_IDirectSoundCaptureBuffer_Start(ma_IDirectSoundCaptureBuffer* pThis, DWORD dwFlags) {
return pThis->lpVtbl->Start(pThis, dwFlags); }
10042 HRESULT ma_IDirectSoundCaptureBuffer_Stop(ma_IDirectSoundCaptureBuffer* pThis) {
return pThis->lpVtbl->Stop(pThis); }
10043 HRESULT ma_IDirectSoundCaptureBuffer_Unlock(ma_IDirectSoundCaptureBuffer* pThis,
void* pAudioPtr1, DWORD dwAudioBytes1,
void* pAudioPtr2, DWORD dwAudioBytes2) {
return pThis->lpVtbl->Unlock(pThis, pAudioPtr1, dwAudioBytes1, pAudioPtr2, dwAudioBytes2); }
10050 HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IDirectSoundNotify* pThis,
const IID*
const riid,
void** ppObject);
10051 ULONG (STDMETHODCALLTYPE * AddRef) (ma_IDirectSoundNotify* pThis);
10052 ULONG (STDMETHODCALLTYPE * Release) (ma_IDirectSoundNotify* pThis);
10055 HRESULT (STDMETHODCALLTYPE * SetNotificationPositions)(ma_IDirectSoundNotify* pThis, DWORD dwPositionNotifies,
const MA_DSBPOSITIONNOTIFY* pPositionNotifies);
10056 } ma_IDirectSoundNotifyVtbl;
10057 struct ma_IDirectSoundNotify
10059 ma_IDirectSoundNotifyVtbl* lpVtbl;
10061 HRESULT ma_IDirectSoundNotify_QueryInterface(ma_IDirectSoundNotify* pThis,
const IID*
const riid,
void** ppObject) {
return pThis->lpVtbl->QueryInterface(pThis, riid, ppObject); }
10062 ULONG ma_IDirectSoundNotify_AddRef(ma_IDirectSoundNotify* pThis) {
return pThis->lpVtbl->AddRef(pThis); }
10063 ULONG ma_IDirectSoundNotify_Release(ma_IDirectSoundNotify* pThis) {
return pThis->lpVtbl->Release(pThis); }
10064 HRESULT ma_IDirectSoundNotify_SetNotificationPositions(ma_IDirectSoundNotify* pThis, DWORD dwPositionNotifies,
const MA_DSBPOSITIONNOTIFY* pPositionNotifies) {
return pThis->lpVtbl->SetNotificationPositions(pThis, dwPositionNotifies, pPositionNotifies); }
10067 typedef BOOL (CALLBACK * ma_DSEnumCallbackAProc) (LPGUID pDeviceGUID, LPCSTR pDeviceDescription, LPCSTR pModule, LPVOID pContext);
10068 typedef HRESULT (WINAPI * ma_DirectSoundCreateProc) (
const GUID* pcGuidDevice, ma_IDirectSound** ppDS8, LPUNKNOWN pUnkOuter);
10069 typedef HRESULT (WINAPI * ma_DirectSoundEnumerateAProc) (ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
10070 typedef HRESULT (WINAPI * ma_DirectSoundCaptureCreateProc) (
const GUID* pcGuidDevice, ma_IDirectSoundCapture** ppDSC8, LPUNKNOWN pUnkOuter);
10071 typedef HRESULT (WINAPI * ma_DirectSoundCaptureEnumerateAProc)(ma_DSEnumCallbackAProc pDSEnumCallback, LPVOID pContext);
10078 void ma_get_channels_from_speaker_config__dsound(DWORD speakerConfig, WORD* pChannelsOut, DWORD* pChannelMapOut)
10084 if (pChannelsOut !=
NULL) {
10085 channels = *pChannelsOut;
10089 if (pChannelMapOut !=
NULL) {
10090 channelMap = *pChannelMapOut;
10097 switch ((BYTE)(speakerConfig)) {
10098 case 1 : channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
break;
10099 case 2 : channels = 1; channelMap = SPEAKER_FRONT_CENTER;
break;
10100 case 3 : channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
break;
10101 case 4 : channels = 2; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
break;
10102 case 5 : channels = 4; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER;
break;
10103 case 6 : channels = 6; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
break;
10104 case 7 : channels = 8; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER;
break;
10105 case 8 : channels = 8; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
break;
10106 case 9 : channels = 6; channelMap = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
break;
10110 if (pChannelsOut !=
NULL) {
10111 *pChannelsOut = channels;
10114 if (pChannelMapOut !=
NULL) {
10115 *pChannelMapOut = channelMap;
10122 ma_IDirectSound* pDirectSound;
10125 ma_assert(pContext !=
NULL);
10126 ma_assert(ppDirectSound !=
NULL);
10128 *ppDirectSound =
NULL;
10129 pDirectSound =
NULL;
10131 if (FAILED(((ma_DirectSoundCreateProc)pContext->dsound.DirectSoundCreate)((pDeviceID ==
NULL) ?
NULL : (
const GUID*)pDeviceID->dsound, &pDirectSound,
NULL))) {
10136 hWnd = ((MA_PFN_GetForegroundWindow)pContext->win32.GetForegroundWindow)();
10137 if (hWnd ==
NULL) {
10138 hWnd = ((MA_PFN_GetDesktopWindow)pContext->win32.GetDesktopWindow)();
10140 if (FAILED(ma_IDirectSound_SetCooperativeLevel(pDirectSound, hWnd, (shareMode ==
ma_share_mode_exclusive) ? MA_DSSCL_EXCLUSIVE : MA_DSSCL_PRIORITY))) {
10144 *ppDirectSound = pDirectSound;
10150 ma_IDirectSoundCapture* pDirectSoundCapture;
10152 ma_assert(pContext !=
NULL);
10153 ma_assert(ppDirectSoundCapture !=
NULL);
10160 *ppDirectSoundCapture =
NULL;
10161 pDirectSoundCapture =
NULL;
10163 if (FAILED(((ma_DirectSoundCaptureCreateProc)pContext->dsound.DirectSoundCaptureCreate)((pDeviceID ==
NULL) ?
NULL : (
const GUID*)pDeviceID->dsound, &pDirectSoundCapture,
NULL))) {
10167 *ppDirectSoundCapture = pDirectSoundCapture;
10171 ma_result ma_context_get_format_info_for_IDirectSoundCapture__dsound(
ma_context* pContext, ma_IDirectSoundCapture* pDirectSoundCapture, WORD* pChannels, WORD* pBitsPerSample, DWORD* pSampleRate)
10174 WORD bitsPerSample;
10177 ma_assert(pContext !=
NULL);
10178 ma_assert(pDirectSoundCapture !=
NULL);
10183 if (pBitsPerSample) {
10184 *pBitsPerSample = 0;
10190 ma_zero_object(&caps);
10191 caps.dwSize =
sizeof(caps);
10192 if (FAILED(ma_IDirectSoundCapture_GetCaps(pDirectSoundCapture, &caps))) {
10197 *pChannels = (WORD)caps.dwChannels;
10201 bitsPerSample = 16;
10202 sampleRate = 48000;
10204 if (caps.dwChannels == 1) {
10205 if ((caps.dwFormats & WAVE_FORMAT_48M16) != 0) {
10206 sampleRate = 48000;
10207 }
else if ((caps.dwFormats & WAVE_FORMAT_44M16) != 0) {
10208 sampleRate = 44100;
10209 }
else if ((caps.dwFormats & WAVE_FORMAT_2M16) != 0) {
10210 sampleRate = 22050;
10211 }
else if ((caps.dwFormats & WAVE_FORMAT_1M16) != 0) {
10212 sampleRate = 11025;
10213 }
else if ((caps.dwFormats & WAVE_FORMAT_96M16) != 0) {
10214 sampleRate = 96000;
10217 if ((caps.dwFormats & WAVE_FORMAT_48M08) != 0) {
10218 sampleRate = 48000;
10219 }
else if ((caps.dwFormats & WAVE_FORMAT_44M08) != 0) {
10220 sampleRate = 44100;
10221 }
else if ((caps.dwFormats & WAVE_FORMAT_2M08) != 0) {
10222 sampleRate = 22050;
10223 }
else if ((caps.dwFormats & WAVE_FORMAT_1M08) != 0) {
10224 sampleRate = 11025;
10225 }
else if ((caps.dwFormats & WAVE_FORMAT_96M08) != 0) {
10226 sampleRate = 96000;
10228 bitsPerSample = 16;
10231 }
else if (caps.dwChannels == 2) {
10232 if ((caps.dwFormats & WAVE_FORMAT_48S16) != 0) {
10233 sampleRate = 48000;
10234 }
else if ((caps.dwFormats & WAVE_FORMAT_44S16) != 0) {
10235 sampleRate = 44100;
10236 }
else if ((caps.dwFormats & WAVE_FORMAT_2S16) != 0) {
10237 sampleRate = 22050;
10238 }
else if ((caps.dwFormats & WAVE_FORMAT_1S16) != 0) {
10239 sampleRate = 11025;
10240 }
else if ((caps.dwFormats & WAVE_FORMAT_96S16) != 0) {
10241 sampleRate = 96000;
10244 if ((caps.dwFormats & WAVE_FORMAT_48S08) != 0) {
10245 sampleRate = 48000;
10246 }
else if ((caps.dwFormats & WAVE_FORMAT_44S08) != 0) {
10247 sampleRate = 44100;
10248 }
else if ((caps.dwFormats & WAVE_FORMAT_2S08) != 0) {
10249 sampleRate = 22050;
10250 }
else if ((caps.dwFormats & WAVE_FORMAT_1S08) != 0) {
10251 sampleRate = 11025;
10252 }
else if ((caps.dwFormats & WAVE_FORMAT_96S08) != 0) {
10253 sampleRate = 96000;
10255 bitsPerSample = 16;
10260 if (pBitsPerSample) {
10261 *pBitsPerSample = bitsPerSample;
10264 *pSampleRate = sampleRate;
10272 ma_assert(pContext !=
NULL);
10273 ma_assert(pID0 !=
NULL);
10274 ma_assert(pID1 !=
NULL);
10277 return memcmp(pID0->dsound, pID1->dsound,
sizeof(pID0->dsound)) == 0;
10288 } ma_context_enumerate_devices_callback_data__dsound;
10290 BOOL CALLBACK ma_context_enumerate_devices_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
10292 ma_context_enumerate_devices_callback_data__dsound* pData = (ma_context_enumerate_devices_callback_data__dsound*)lpContext;
10295 ma_zero_object(&deviceInfo);
10298 if (lpGuid !=
NULL) {
10299 ma_copy_memory(deviceInfo.
id.dsound, lpGuid, 16);
10301 ma_zero_memory(deviceInfo.
id.dsound, 16);
10305 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), lpcstrDescription, (
size_t)-1);
10309 ma_assert(pData !=
NULL);
10310 pData->terminated = !pData->callback(pData->pContext, pData->deviceType, &deviceInfo, pData->pUserData);
10311 if (pData->terminated) {
10317 (
void)lpcstrModule;
10322 ma_context_enumerate_devices_callback_data__dsound
data;
10324 ma_assert(pContext !=
NULL);
10325 ma_assert(callback !=
NULL);
10327 data.pContext = pContext;
10328 data.callback = callback;
10333 if (!
data.terminated) {
10335 ((ma_DirectSoundEnumerateAProc)pContext->dsound.DirectSoundEnumerateA)(ma_context_enumerate_devices_callback__dsound, &
data);
10339 if (!
data.terminated) {
10341 ((ma_DirectSoundCaptureEnumerateAProc)pContext->dsound.DirectSoundCaptureEnumerateA)(ma_context_enumerate_devices_callback__dsound, &
data);
10353 } ma_context_get_device_info_callback_data__dsound;
10355 BOOL CALLBACK ma_context_get_device_info_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
10357 ma_context_get_device_info_callback_data__dsound* pData = (ma_context_get_device_info_callback_data__dsound*)lpContext;
10358 ma_assert(pData !=
NULL);
10360 if ((pData->pDeviceID ==
NULL || ma_is_guid_equal(pData->pDeviceID->dsound, &MA_GUID_NULL)) && (lpGuid ==
NULL || ma_is_guid_equal(lpGuid, &MA_GUID_NULL))) {
10362 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), lpcstrDescription, (
size_t)-1);
10367 if (lpGuid !=
NULL) {
10368 if (memcmp(pData->pDeviceID->dsound, lpGuid,
sizeof(pData->pDeviceID->dsound)) == 0) {
10369 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), lpcstrDescription, (
size_t)-1);
10376 (
void)lpcstrModule;
10387 if (pDeviceID !=
NULL) {
10388 ma_context_get_device_info_callback_data__dsound
data;
10391 ma_copy_memory(pDeviceInfo->
id.dsound, pDeviceID->dsound, 16);
10394 data.pDeviceID = pDeviceID;
10395 data.pDeviceInfo = pDeviceInfo;
10398 ((ma_DirectSoundEnumerateAProc)pContext->dsound.DirectSoundEnumerateA)(ma_context_get_device_info_callback__dsound, &
data);
10400 ((ma_DirectSoundCaptureEnumerateAProc)pContext->dsound.DirectSoundCaptureEnumerateA)(ma_context_get_device_info_callback__dsound, &
data);
10410 ma_zero_memory(pDeviceInfo->
id.dsound, 16);
10414 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
10416 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
10423 ma_IDirectSound* pDirectSound;
10428 result = ma_context_create_IDirectSound__dsound(pContext, shareMode, pDeviceID, &pDirectSound);
10433 ma_zero_object(&caps);
10434 caps.dwSize =
sizeof(caps);
10435 if (FAILED(ma_IDirectSound_GetCaps(pDirectSound, &caps))) {
10439 if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
10444 DWORD speakerConfig;
10445 if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig(pDirectSound, &speakerConfig))) {
10446 ma_get_channels_from_speaker_config__dsound(speakerConfig, &channels,
NULL);
10458 if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
10459 pDeviceInfo->
minSampleRate = caps.dwMinSecondarySampleRate;
10460 pDeviceInfo->
maxSampleRate = caps.dwMaxSecondarySampleRate;
10474 pDeviceInfo->
minSampleRate = caps.dwMaxSecondarySampleRate;
10475 pDeviceInfo->
maxSampleRate = caps.dwMaxSecondarySampleRate;
10480 for (iFormat = 0; iFormat < pDeviceInfo->
formatCount; ++iFormat) {
10484 ma_IDirectSound_Release(pDirectSound);
10491 ma_IDirectSoundCapture* pDirectSoundCapture;
10494 WORD bitsPerSample;
10497 result = ma_context_create_IDirectSoundCapture__dsound(pContext, shareMode, pDeviceID, &pDirectSoundCapture);
10502 result = ma_context_get_format_info_for_IDirectSoundCapture__dsound(pContext, pDirectSoundCapture, &channels, &bitsPerSample, &sampleRate);
10504 ma_IDirectSoundCapture_Release(pDirectSoundCapture);
10513 if (bitsPerSample == 8) {
10515 }
else if (bitsPerSample == 16) {
10517 }
else if (bitsPerSample == 24) {
10519 }
else if (bitsPerSample == 32) {
10522 ma_IDirectSoundCapture_Release(pDirectSoundCapture);
10526 ma_IDirectSoundCapture_Release(pDirectSoundCapture);
10538 } ma_device_enum_data__dsound;
10540 BOOL CALLBACK ma_enum_devices_callback__dsound(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
10542 ma_device_enum_data__dsound* pData = (ma_device_enum_data__dsound*)lpContext;
10543 ma_assert(pData !=
NULL);
10545 if (pData->pInfo !=
NULL) {
10546 if (pData->infoCount > 0) {
10547 ma_zero_object(pData->pInfo);
10548 ma_strncpy_s(pData->pInfo->name,
sizeof(pData->pInfo->name), lpcstrDescription, (
size_t)-1);
10550 if (lpGuid !=
NULL) {
10551 ma_copy_memory(pData->pInfo->id.dsound, lpGuid, 16);
10553 ma_zero_memory(pData->pInfo->id.dsound, 16);
10557 pData->infoCount -= 1;
10558 pData->deviceCount += 1;
10561 pData->deviceCount += 1;
10564 (
void)lpcstrModule;
10568 void ma_device_uninit__dsound(
ma_device* pDevice)
10570 ma_assert(pDevice !=
NULL);
10572 if (pDevice->dsound.pCaptureBuffer !=
NULL) {
10573 ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
10575 if (pDevice->dsound.pCapture !=
NULL) {
10576 ma_IDirectSoundCapture_Release((ma_IDirectSoundCapture*)pDevice->dsound.pCapture);
10579 if (pDevice->dsound.pPlaybackBuffer !=
NULL) {
10580 ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer);
10582 if (pDevice->dsound.pPlaybackPrimaryBuffer !=
NULL) {
10583 ma_IDirectSoundBuffer_Release((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer);
10585 if (pDevice->dsound.pPlayback !=
NULL) {
10586 ma_IDirectSound_Release((ma_IDirectSound*)pDevice->dsound.pPlayback);
10602 subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
10607 subformat = MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
10614 ma_zero_object(pWF);
10615 pWF->Format.cbSize =
sizeof(*pWF);
10616 pWF->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
10617 pWF->Format.nChannels = (WORD)channels;
10618 pWF->Format.nSamplesPerSec = (DWORD)sampleRate;
10620 pWF->Format.nBlockAlign = (pWF->Format.nChannels * pWF->Format.wBitsPerSample) / 8;
10621 pWF->Format.nAvgBytesPerSec = pWF->Format.nBlockAlign * pWF->Format.nSamplesPerSec;
10622 pWF->Samples.wValidBitsPerSample = pWF->Format.wBitsPerSample;
10623 pWF->dwChannelMask = ma_channel_map_to_channel_mask__win32(pChannelMap, channels);
10624 pWF->SubFormat = subformat;
10634 ma_assert(pDevice !=
NULL);
10635 ma_zero_object(&pDevice->dsound);
10642 if (bufferSizeInMilliseconds == 0) {
10647 if (pDevice->usingDefaultBufferSize) {
10649 bufferSizeInMilliseconds = 20 * pConfig->
periods;
10651 bufferSizeInMilliseconds = 200 * pConfig->
periods;
10656 if ((bufferSizeInMilliseconds/pConfig->
periods) < 20) {
10657 bufferSizeInMilliseconds = pConfig->
periods * 20;
10666 WAVEFORMATEXTENSIBLE wf;
10667 MA_DSCBUFFERDESC descDS;
10669 char rawdata[1024];
10670 WAVEFORMATEXTENSIBLE* pActualFormat;
10679 ma_device_uninit__dsound(pDevice);
10683 result = ma_context_get_format_info_for_IDirectSoundCapture__dsound(pContext, (ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &wf.Format.nChannels, &wf.Format.wBitsPerSample, &wf.Format.nSamplesPerSec);
10685 ma_device_uninit__dsound(pDevice);
10689 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
10690 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
10691 wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
10692 wf.SubFormat = MA_GUID_KSDATAFORMAT_SUBTYPE_PCM;
10697 ma_zero_object(&descDS);
10698 descDS.dwSize =
sizeof(descDS);
10699 descDS.dwFlags = 0;
10700 descDS.dwBufferBytes = bufferSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, wf.Format.nChannels);
10701 descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
10702 if (FAILED(ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer,
NULL))) {
10703 ma_device_uninit__dsound(pDevice);
10708 pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
10709 if (FAILED(ma_IDirectSoundCaptureBuffer_GetFormat((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, (WAVEFORMATEX*)pActualFormat,
sizeof(rawdata),
NULL))) {
10710 ma_device_uninit__dsound(pDevice);
10714 pDevice->capture.internalFormat = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
10715 pDevice->capture.internalChannels = pActualFormat->Format.nChannels;
10716 pDevice->capture.internalSampleRate = pActualFormat->Format.nSamplesPerSec;
10719 if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
10720 ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDevice->capture.internalChannels, pDevice->capture.internalChannelMap);
10722 ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDevice->capture.internalChannels, pDevice->capture.internalChannelMap);
10729 if (bufferSizeInFrames != (descDS.dwBufferBytes / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels))) {
10730 descDS.dwBufferBytes = bufferSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, wf.Format.nChannels);
10731 ma_IDirectSoundCaptureBuffer_Release((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
10733 if (FAILED(ma_IDirectSoundCapture_CreateCaptureBuffer((ma_IDirectSoundCapture*)pDevice->dsound.pCapture, &descDS, (ma_IDirectSoundCaptureBuffer**)&pDevice->dsound.pCaptureBuffer,
NULL))) {
10734 ma_device_uninit__dsound(pDevice);
10740 pDevice->capture.internalBufferSizeInFrames = bufferSizeInFrames;
10741 pDevice->capture.internalPeriods = pConfig->
periods;
10745 WAVEFORMATEXTENSIBLE wf;
10746 MA_DSBUFFERDESC descDSPrimary;
10748 char rawdata[1024];
10749 WAVEFORMATEXTENSIBLE* pActualFormat;
10751 MA_DSBUFFERDESC descDS;
10760 ma_device_uninit__dsound(pDevice);
10764 ma_zero_object(&descDSPrimary);
10765 descDSPrimary.dwSize =
sizeof(MA_DSBUFFERDESC);
10766 descDSPrimary.dwFlags = MA_DSBCAPS_PRIMARYBUFFER | MA_DSBCAPS_CTRLVOLUME;
10767 if (FAILED(ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDSPrimary, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackPrimaryBuffer,
NULL))) {
10768 ma_device_uninit__dsound(pDevice);
10774 ma_zero_object(&caps);
10775 caps.dwSize =
sizeof(caps);
10776 if (FAILED(ma_IDirectSound_GetCaps((ma_IDirectSound*)pDevice->dsound.pPlayback, &caps))) {
10777 ma_device_uninit__dsound(pDevice);
10781 if (pDevice->playback.usingDefaultChannels) {
10782 if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
10783 DWORD speakerConfig;
10786 wf.Format.nChannels = 2;
10789 if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig((ma_IDirectSound*)pDevice->dsound.pPlayback, &speakerConfig))) {
10790 ma_get_channels_from_speaker_config__dsound(speakerConfig, &wf.Format.nChannels, &wf.dwChannelMask);
10794 wf.Format.nChannels = 1;
10798 if (pDevice->usingDefaultSampleRate) {
10800 if ((caps.dwFlags & MA_DSCAPS_CONTINUOUSRATE) != 0) {
10801 wf.Format.nSamplesPerSec = ma_get_best_sample_rate_within_range(caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate);
10803 wf.Format.nSamplesPerSec = caps.dwMaxSecondarySampleRate;
10807 wf.Format.nBlockAlign = (wf.Format.nChannels * wf.Format.wBitsPerSample) / 8;
10808 wf.Format.nAvgBytesPerSec = wf.Format.nBlockAlign * wf.Format.nSamplesPerSec;
10817 if (FAILED(ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)&wf))) {
10818 ma_device_uninit__dsound(pDevice);
10823 pActualFormat = (WAVEFORMATEXTENSIBLE*)rawdata;
10824 if (FAILED(ma_IDirectSoundBuffer_GetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)pActualFormat,
sizeof(rawdata),
NULL))) {
10825 ma_device_uninit__dsound(pDevice);
10829 pDevice->playback.internalFormat = ma_format_from_WAVEFORMATEX((WAVEFORMATEX*)pActualFormat);
10830 pDevice->playback.internalChannels = pActualFormat->Format.nChannels;
10831 pDevice->playback.internalSampleRate = pActualFormat->Format.nSamplesPerSec;
10834 if (pActualFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
10835 ma_channel_mask_to_channel_map__win32(pActualFormat->dwChannelMask, pDevice->playback.internalChannels, pDevice->playback.internalChannelMap);
10837 ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pDevice->playback.internalChannels, pDevice->playback.internalChannelMap);
10858 ma_zero_object(&descDS);
10859 descDS.dwSize =
sizeof(descDS);
10860 descDS.dwFlags = MA_DSBCAPS_CTRLPOSITIONNOTIFY | MA_DSBCAPS_GLOBALFOCUS | MA_DSBCAPS_GETCURRENTPOSITION2;
10861 descDS.dwBufferBytes = bufferSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
10862 descDS.lpwfxFormat = (WAVEFORMATEX*)&wf;
10863 if (FAILED(ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDS, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackBuffer,
NULL))) {
10864 ma_device_uninit__dsound(pDevice);
10869 pDevice->playback.internalBufferSizeInFrames = bufferSizeInFrames;
10870 pDevice->playback.internalPeriods = pConfig->
periods;
10881 ma_uint32 bpfCapture = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
10882 ma_uint32 bpfPlayback = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
10884 DWORD lockOffsetInBytesCapture;
10885 DWORD lockSizeInBytesCapture;
10886 DWORD mappedSizeInBytesCapture;
10887 void* pMappedBufferCapture;
10888 DWORD lockOffsetInBytesPlayback;
10889 DWORD lockSizeInBytesPlayback;
10890 DWORD mappedSizeInBytesPlayback;
10891 void* pMappedBufferPlayback;
10892 DWORD prevReadCursorInBytesCapture = 0;
10893 DWORD prevPlayCursorInBytesPlayback = 0;
10894 ma_bool32 physicalPlayCursorLoopFlagPlayback = 0;
10895 DWORD virtualWriteCursorInBytesPlayback = 0;
10896 ma_bool32 virtualWriteCursorLoopFlagPlayback = 0;
10898 ma_uint32 framesWrittenToPlaybackDevice = 0;
10901 ma_assert(pDevice !=
NULL);
10905 if (FAILED(ma_IDirectSoundCaptureBuffer_Start((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, MA_DSCBSTART_LOOPING))) {
10910 while (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
10911 switch (pDevice->type)
10915 DWORD physicalCaptureCursorInBytes;
10916 DWORD physicalReadCursorInBytes;
10917 if (FAILED(ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes))) {
10922 if (physicalReadCursorInBytes == prevReadCursorInBytesCapture) {
10923 ma_sleep(waitTimeInMilliseconds);
10931 if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
10933 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
10934 lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
10940 if (prevReadCursorInBytesCapture < pDevice->capture.internalBufferSizeInFrames*bpfCapture) {
10942 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
10943 lockSizeInBytesCapture = (pDevice->capture.internalBufferSizeInFrames*bpfCapture) - prevReadCursorInBytesCapture;
10946 lockOffsetInBytesCapture = 0;
10947 lockSizeInBytesCapture = physicalReadCursorInBytes;
10951 if (lockSizeInBytesCapture == 0) {
10952 ma_sleep(waitTimeInMilliseconds);
10956 hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedBufferCapture, &mappedSizeInBytesCapture,
NULL,
NULL, 0);
10963 pDevice->capture._dspFrameCount = mappedSizeInBytesCapture / bpfCapture;
10964 pDevice->capture._dspFrames = (
const ma_uint8*)pMappedBufferCapture;
10966 ma_uint8 inputFramesInExternalFormat[4096];
10967 ma_uint32 inputFramesInExternalFormatCap =
sizeof(inputFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
10968 ma_uint32 inputFramesInExternalFormatCount;
10969 ma_uint8 outputFramesInExternalFormat[4096];
10970 ma_uint32 outputFramesInExternalFormatCap =
sizeof(outputFramesInExternalFormat) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
10972 inputFramesInExternalFormatCount = (
ma_uint32)
ma_pcm_converter_read(&pDevice->capture.converter, inputFramesInExternalFormat, ma_min(inputFramesInExternalFormatCap, outputFramesInExternalFormatCap));
10973 if (inputFramesInExternalFormatCount == 0) {
10977 ma_device__on_data(pDevice, outputFramesInExternalFormat, inputFramesInExternalFormat, inputFramesInExternalFormatCount);
10980 pDevice->playback._dspFrameCount = inputFramesInExternalFormatCount;
10981 pDevice->playback._dspFrames = (
const ma_uint8*)outputFramesInExternalFormat;
10984 DWORD physicalPlayCursorInBytes;
10985 DWORD physicalWriteCursorInBytes;
10986 DWORD availableBytesPlayback;
10987 DWORD silentPaddingInBytes = 0;
10990 if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
10994 if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
10995 physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
10997 prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
11000 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11002 if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
11003 availableBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
11004 availableBytesPlayback += physicalPlayCursorInBytes;
11007 #ifdef MA_DEBUG_OUTPUT
11008 printf(
"[DirectSound] (Duplex/Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11010 availableBytesPlayback = 0;
11014 if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
11015 availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11018 #ifdef MA_DEBUG_OUTPUT
11019 printf(
"[DirectSound] (Duplex/Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11021 availableBytesPlayback = 0;
11025 #ifdef MA_DEBUG_OUTPUT
11030 if (availableBytesPlayback == 0) {
11032 if (!isPlaybackDeviceStarted) {
11033 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
11034 ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
11037 isPlaybackDeviceStarted =
MA_TRUE;
11039 ma_sleep(waitTimeInMilliseconds);
11046 lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
11047 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11049 lockSizeInBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
11052 lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11055 hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedBufferPlayback, &mappedSizeInBytesPlayback,
NULL,
NULL, 0);
11065 if (isPlaybackDeviceStarted) {
11066 DWORD bytesQueuedForPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - availableBytesPlayback;
11067 if (bytesQueuedForPlayback < ((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*bpfPlayback)) {
11068 silentPaddingInBytes = ((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*2*bpfPlayback) - bytesQueuedForPlayback;
11069 if (silentPaddingInBytes > lockSizeInBytesPlayback) {
11070 silentPaddingInBytes = lockSizeInBytesPlayback;
11073 #ifdef MA_DEBUG_OUTPUT
11074 printf(
"[DirectSound] (Duplex/Playback) Playback buffer starved. availableBytesPlayback=%d, silentPaddingInBytes=%d\n", availableBytesPlayback, silentPaddingInBytes);
11080 if (silentPaddingInBytes > 0) {
11081 ma_zero_memory(pMappedBufferPlayback, silentPaddingInBytes);
11082 framesWrittenThisIteration = silentPaddingInBytes/bpfPlayback;
11084 framesWrittenThisIteration = (
ma_uint32)
ma_pcm_converter_read(&pDevice->playback.converter, pMappedBufferPlayback, mappedSizeInBytesPlayback/bpfPlayback);
11088 hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedBufferPlayback, framesWrittenThisIteration*bpfPlayback,
NULL, 0);
11094 virtualWriteCursorInBytesPlayback += framesWrittenThisIteration*bpfPlayback;
11095 if ((virtualWriteCursorInBytesPlayback/bpfPlayback) == pDevice->playback.internalBufferSizeInFrames) {
11096 virtualWriteCursorInBytesPlayback = 0;
11097 virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
11104 framesWrittenToPlaybackDevice += framesWrittenThisIteration;
11105 if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= ((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)*2)) {
11106 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
11107 ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer);
11110 isPlaybackDeviceStarted =
MA_TRUE;
11113 if (framesWrittenThisIteration < mappedSizeInBytesPlayback/bpfPlayback) {
11118 if (inputFramesInExternalFormatCount < inputFramesInExternalFormatCap) {
11125 hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedBufferCapture, mappedSizeInBytesCapture,
NULL, 0);
11129 prevReadCursorInBytesCapture = (lockOffsetInBytesCapture + mappedSizeInBytesCapture);
11136 DWORD physicalCaptureCursorInBytes;
11137 DWORD physicalReadCursorInBytes;
11138 if (FAILED(ma_IDirectSoundCaptureBuffer_GetCurrentPosition((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, &physicalCaptureCursorInBytes, &physicalReadCursorInBytes))) {
11143 if (prevReadCursorInBytesCapture == physicalReadCursorInBytes) {
11144 ma_sleep(waitTimeInMilliseconds);
11149 if (prevReadCursorInBytesCapture < physicalReadCursorInBytes) {
11151 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
11152 lockSizeInBytesCapture = (physicalReadCursorInBytes - prevReadCursorInBytesCapture);
11158 if (prevReadCursorInBytesCapture < pDevice->capture.internalBufferSizeInFrames*bpfCapture) {
11160 lockOffsetInBytesCapture = prevReadCursorInBytesCapture;
11161 lockSizeInBytesCapture = (pDevice->capture.internalBufferSizeInFrames*bpfCapture) - prevReadCursorInBytesCapture;
11164 lockOffsetInBytesCapture = 0;
11165 lockSizeInBytesCapture = physicalReadCursorInBytes;
11169 #ifdef MA_DEBUG_OUTPUT
11174 if (lockSizeInBytesCapture < (pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods)) {
11175 ma_sleep(waitTimeInMilliseconds);
11179 hr = ma_IDirectSoundCaptureBuffer_Lock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, lockOffsetInBytesCapture, lockSizeInBytesCapture, &pMappedBufferCapture, &mappedSizeInBytesCapture,
NULL,
NULL, 0);
11184 #ifdef MA_DEBUG_OUTPUT
11185 if (lockSizeInBytesCapture != mappedSizeInBytesCapture) {
11186 printf(
"[DirectSound] (Capture) lockSizeInBytesCapture=%d != mappedSizeInBytesCapture=%d\n", lockSizeInBytesCapture, mappedSizeInBytesCapture);
11190 ma_device__send_frames_to_client(pDevice, mappedSizeInBytesCapture/bpfCapture, pMappedBufferCapture);
11192 hr = ma_IDirectSoundCaptureBuffer_Unlock((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer, pMappedBufferCapture, mappedSizeInBytesCapture,
NULL, 0);
11196 prevReadCursorInBytesCapture = lockOffsetInBytesCapture + mappedSizeInBytesCapture;
11198 if (prevReadCursorInBytesCapture == (pDevice->capture.internalBufferSizeInFrames*bpfCapture)) {
11199 prevReadCursorInBytesCapture = 0;
11207 DWORD availableBytesPlayback;
11208 DWORD physicalPlayCursorInBytes;
11209 DWORD physicalWriteCursorInBytes;
11210 if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
11214 if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
11215 physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
11217 prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
11220 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11222 if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
11223 availableBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
11224 availableBytesPlayback += physicalPlayCursorInBytes;
11227 #ifdef MA_DEBUG_OUTPUT
11228 printf(
"[DirectSound] (Playback) WARNING: Play cursor has moved in front of the write cursor (same loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11230 availableBytesPlayback = 0;
11234 if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
11235 availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11238 #ifdef MA_DEBUG_OUTPUT
11239 printf(
"[DirectSound] (Playback) WARNING: Write cursor has moved behind the play cursor (different loop iterations). physicalPlayCursorInBytes=%d, virtualWriteCursorInBytes=%d.\n", physicalPlayCursorInBytes, virtualWriteCursorInBytesPlayback);
11241 availableBytesPlayback = 0;
11245 #ifdef MA_DEBUG_OUTPUT
11250 if (availableBytesPlayback < (pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)) {
11252 if (availableBytesPlayback == 0 && !isPlaybackDeviceStarted) {
11253 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
11256 isPlaybackDeviceStarted =
MA_TRUE;
11258 ma_sleep(waitTimeInMilliseconds);
11264 lockOffsetInBytesPlayback = virtualWriteCursorInBytesPlayback;
11265 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11267 lockSizeInBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
11270 lockSizeInBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11273 hr = ma_IDirectSoundBuffer_Lock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, lockOffsetInBytesPlayback, lockSizeInBytesPlayback, &pMappedBufferPlayback, &mappedSizeInBytesPlayback,
NULL,
NULL, 0);
11280 ma_device__read_frames_from_client(pDevice, (mappedSizeInBytesPlayback/bpfPlayback), pMappedBufferPlayback);
11282 hr = ma_IDirectSoundBuffer_Unlock((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, pMappedBufferPlayback, mappedSizeInBytesPlayback,
NULL, 0);
11288 virtualWriteCursorInBytesPlayback += mappedSizeInBytesPlayback;
11289 if (virtualWriteCursorInBytesPlayback == pDevice->playback.internalBufferSizeInFrames*bpfPlayback) {
11290 virtualWriteCursorInBytesPlayback = 0;
11291 virtualWriteCursorLoopFlagPlayback = !virtualWriteCursorLoopFlagPlayback;
11298 framesWrittenToPlaybackDevice += mappedSizeInBytesPlayback/bpfPlayback;
11299 if (!isPlaybackDeviceStarted && framesWrittenToPlaybackDevice >= (pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods)) {
11300 if (FAILED(ma_IDirectSoundBuffer_Play((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0, 0, MA_DSBPLAY_LOOPING))) {
11303 isPlaybackDeviceStarted =
MA_TRUE;
11318 if (FAILED(ma_IDirectSoundCaptureBuffer_Stop((ma_IDirectSoundCaptureBuffer*)pDevice->dsound.pCaptureBuffer))) {
11325 if (isPlaybackDeviceStarted) {
11327 DWORD availableBytesPlayback = 0;
11328 DWORD physicalPlayCursorInBytes;
11329 DWORD physicalWriteCursorInBytes;
11330 if (FAILED(ma_IDirectSoundBuffer_GetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, &physicalPlayCursorInBytes, &physicalWriteCursorInBytes))) {
11334 if (physicalPlayCursorInBytes < prevPlayCursorInBytesPlayback) {
11335 physicalPlayCursorLoopFlagPlayback = !physicalPlayCursorLoopFlagPlayback;
11337 prevPlayCursorInBytesPlayback = physicalPlayCursorInBytes;
11339 if (physicalPlayCursorLoopFlagPlayback == virtualWriteCursorLoopFlagPlayback) {
11341 if (physicalPlayCursorInBytes <= virtualWriteCursorInBytesPlayback) {
11342 availableBytesPlayback = (pDevice->playback.internalBufferSizeInFrames*bpfPlayback) - virtualWriteCursorInBytesPlayback;
11343 availableBytesPlayback += physicalPlayCursorInBytes;
11349 if (physicalPlayCursorInBytes >= virtualWriteCursorInBytesPlayback) {
11350 availableBytesPlayback = physicalPlayCursorInBytes - virtualWriteCursorInBytesPlayback;
11356 if (availableBytesPlayback >= (pDevice->playback.internalBufferSizeInFrames*bpfPlayback)) {
11360 ma_sleep(waitTimeInMilliseconds);
11364 if (FAILED(ma_IDirectSoundBuffer_Stop((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer))) {
11368 ma_IDirectSoundBuffer_SetCurrentPosition((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackBuffer, 0);
11376 ma_assert(pContext !=
NULL);
11379 ma_dlclose(pContext, pContext->dsound.hDSoundDLL);
11386 ma_assert(pContext !=
NULL);
11390 pContext->dsound.hDSoundDLL = ma_dlopen(pContext,
"dsound.dll");
11391 if (pContext->dsound.hDSoundDLL ==
NULL) {
11395 pContext->dsound.DirectSoundCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL,
"DirectSoundCreate");
11396 pContext->dsound.DirectSoundEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL,
"DirectSoundEnumerateA");
11397 pContext->dsound.DirectSoundCaptureCreate = ma_dlsym(pContext, pContext->dsound.hDSoundDLL,
"DirectSoundCaptureCreate");
11398 pContext->dsound.DirectSoundCaptureEnumerateA = ma_dlsym(pContext, pContext->dsound.hDSoundDLL,
"DirectSoundCaptureEnumerateA");
11400 pContext->
onUninit = ma_context_uninit__dsound;
11402 pContext->
onEnumDevices = ma_context_enumerate_devices__dsound;
11421 #ifdef MA_HAS_WINMM
11432 MMVERSION vDriverVersion;
11433 CHAR szPname[MAXPNAMELEN];
11438 GUID ManufacturerGuid;
11441 } MA_WAVEOUTCAPS2A;
11446 MMVERSION vDriverVersion;
11447 CHAR szPname[MAXPNAMELEN];
11451 GUID ManufacturerGuid;
11456 typedef UINT (WINAPI * MA_PFN_waveOutGetNumDevs)(
void);
11457 typedef MMRESULT (WINAPI * MA_PFN_waveOutGetDevCapsA)(
ma_uintptr uDeviceID, LPWAVEOUTCAPSA pwoc, UINT cbwoc);
11458 typedef MMRESULT (WINAPI * MA_PFN_waveOutOpen)(LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
11459 typedef MMRESULT (WINAPI * MA_PFN_waveOutClose)(HWAVEOUT hwo);
11460 typedef MMRESULT (WINAPI * MA_PFN_waveOutPrepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
11461 typedef MMRESULT (WINAPI * MA_PFN_waveOutUnprepareHeader)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
11462 typedef MMRESULT (WINAPI * MA_PFN_waveOutWrite)(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
11463 typedef MMRESULT (WINAPI * MA_PFN_waveOutReset)(HWAVEOUT hwo);
11464 typedef UINT (WINAPI * MA_PFN_waveInGetNumDevs)(
void);
11465 typedef MMRESULT (WINAPI * MA_PFN_waveInGetDevCapsA)(
ma_uintptr uDeviceID, LPWAVEINCAPSA pwic, UINT cbwic);
11466 typedef MMRESULT (WINAPI * MA_PFN_waveInOpen)(LPHWAVEIN phwi, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen);
11467 typedef MMRESULT (WINAPI * MA_PFN_waveInClose)(HWAVEIN hwi);
11468 typedef MMRESULT (WINAPI * MA_PFN_waveInPrepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
11469 typedef MMRESULT (WINAPI * MA_PFN_waveInUnprepareHeader)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
11470 typedef MMRESULT (WINAPI * MA_PFN_waveInAddBuffer)(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh);
11471 typedef MMRESULT (WINAPI * MA_PFN_waveInStart)(HWAVEIN hwi);
11472 typedef MMRESULT (WINAPI * MA_PFN_waveInReset)(HWAVEIN hwi);
11474 ma_result ma_result_from_MMRESULT(MMRESULT resultMM)
11476 switch (resultMM) {
11484 case MMSYSERR_ERROR:
return MA_ERROR;
11489 char* ma_find_last_character(
char* str,
char ch)
11498 while (*str !=
'\0') {
11516 CHAR szPname[MAXPNAMELEN];
11522 ma_result ma_get_best_info_from_formats_flags__winmm(DWORD dwFormats, WORD channels, WORD* pBitsPerSample, DWORD* pSampleRate)
11524 WORD bitsPerSample = 0;
11525 DWORD sampleRate = 0;
11527 if (pBitsPerSample) {
11528 *pBitsPerSample = 0;
11534 if (channels == 1) {
11535 bitsPerSample = 16;
11536 if ((dwFormats & WAVE_FORMAT_48M16) != 0) {
11537 sampleRate = 48000;
11538 }
else if ((dwFormats & WAVE_FORMAT_44M16) != 0) {
11539 sampleRate = 44100;
11540 }
else if ((dwFormats & WAVE_FORMAT_2M16) != 0) {
11541 sampleRate = 22050;
11542 }
else if ((dwFormats & WAVE_FORMAT_1M16) != 0) {
11543 sampleRate = 11025;
11544 }
else if ((dwFormats & WAVE_FORMAT_96M16) != 0) {
11545 sampleRate = 96000;
11548 if ((dwFormats & WAVE_FORMAT_48M08) != 0) {
11549 sampleRate = 48000;
11550 }
else if ((dwFormats & WAVE_FORMAT_44M08) != 0) {
11551 sampleRate = 44100;
11552 }
else if ((dwFormats & WAVE_FORMAT_2M08) != 0) {
11553 sampleRate = 22050;
11554 }
else if ((dwFormats & WAVE_FORMAT_1M08) != 0) {
11555 sampleRate = 11025;
11556 }
else if ((dwFormats & WAVE_FORMAT_96M08) != 0) {
11557 sampleRate = 96000;
11563 bitsPerSample = 16;
11564 if ((dwFormats & WAVE_FORMAT_48S16) != 0) {
11565 sampleRate = 48000;
11566 }
else if ((dwFormats & WAVE_FORMAT_44S16) != 0) {
11567 sampleRate = 44100;
11568 }
else if ((dwFormats & WAVE_FORMAT_2S16) != 0) {
11569 sampleRate = 22050;
11570 }
else if ((dwFormats & WAVE_FORMAT_1S16) != 0) {
11571 sampleRate = 11025;
11572 }
else if ((dwFormats & WAVE_FORMAT_96S16) != 0) {
11573 sampleRate = 96000;
11576 if ((dwFormats & WAVE_FORMAT_48S08) != 0) {
11577 sampleRate = 48000;
11578 }
else if ((dwFormats & WAVE_FORMAT_44S08) != 0) {
11579 sampleRate = 44100;
11580 }
else if ((dwFormats & WAVE_FORMAT_2S08) != 0) {
11581 sampleRate = 22050;
11582 }
else if ((dwFormats & WAVE_FORMAT_1S08) != 0) {
11583 sampleRate = 11025;
11584 }
else if ((dwFormats & WAVE_FORMAT_96S08) != 0) {
11585 sampleRate = 96000;
11592 if (pBitsPerSample) {
11593 *pBitsPerSample = bitsPerSample;
11596 *pSampleRate = sampleRate;
11602 ma_result ma_formats_flags_to_WAVEFORMATEX__winmm(DWORD dwFormats, WORD channels, WAVEFORMATEX* pWF)
11604 ma_assert(pWF !=
NULL);
11606 ma_zero_object(pWF);
11607 pWF->cbSize =
sizeof(*pWF);
11608 pWF->wFormatTag = WAVE_FORMAT_PCM;
11609 pWF->nChannels = (WORD)channels;
11610 if (pWF->nChannels > 2) {
11611 pWF->nChannels = 2;
11614 if (channels == 1) {
11615 pWF->wBitsPerSample = 16;
11616 if ((dwFormats & WAVE_FORMAT_48M16) != 0) {
11617 pWF->nSamplesPerSec = 48000;
11618 }
else if ((dwFormats & WAVE_FORMAT_44M16) != 0) {
11619 pWF->nSamplesPerSec = 44100;
11620 }
else if ((dwFormats & WAVE_FORMAT_2M16) != 0) {
11621 pWF->nSamplesPerSec = 22050;
11622 }
else if ((dwFormats & WAVE_FORMAT_1M16) != 0) {
11623 pWF->nSamplesPerSec = 11025;
11624 }
else if ((dwFormats & WAVE_FORMAT_96M16) != 0) {
11625 pWF->nSamplesPerSec = 96000;
11627 pWF->wBitsPerSample = 8;
11628 if ((dwFormats & WAVE_FORMAT_48M08) != 0) {
11629 pWF->nSamplesPerSec = 48000;
11630 }
else if ((dwFormats & WAVE_FORMAT_44M08) != 0) {
11631 pWF->nSamplesPerSec = 44100;
11632 }
else if ((dwFormats & WAVE_FORMAT_2M08) != 0) {
11633 pWF->nSamplesPerSec = 22050;
11634 }
else if ((dwFormats & WAVE_FORMAT_1M08) != 0) {
11635 pWF->nSamplesPerSec = 11025;
11636 }
else if ((dwFormats & WAVE_FORMAT_96M08) != 0) {
11637 pWF->nSamplesPerSec = 96000;
11643 pWF->wBitsPerSample = 16;
11644 if ((dwFormats & WAVE_FORMAT_48S16) != 0) {
11645 pWF->nSamplesPerSec = 48000;
11646 }
else if ((dwFormats & WAVE_FORMAT_44S16) != 0) {
11647 pWF->nSamplesPerSec = 44100;
11648 }
else if ((dwFormats & WAVE_FORMAT_2S16) != 0) {
11649 pWF->nSamplesPerSec = 22050;
11650 }
else if ((dwFormats & WAVE_FORMAT_1S16) != 0) {
11651 pWF->nSamplesPerSec = 11025;
11652 }
else if ((dwFormats & WAVE_FORMAT_96S16) != 0) {
11653 pWF->nSamplesPerSec = 96000;
11655 pWF->wBitsPerSample = 8;
11656 if ((dwFormats & WAVE_FORMAT_48S08) != 0) {
11657 pWF->nSamplesPerSec = 48000;
11658 }
else if ((dwFormats & WAVE_FORMAT_44S08) != 0) {
11659 pWF->nSamplesPerSec = 44100;
11660 }
else if ((dwFormats & WAVE_FORMAT_2S08) != 0) {
11661 pWF->nSamplesPerSec = 22050;
11662 }
else if ((dwFormats & WAVE_FORMAT_1S08) != 0) {
11663 pWF->nSamplesPerSec = 11025;
11664 }
else if ((dwFormats & WAVE_FORMAT_96S08) != 0) {
11665 pWF->nSamplesPerSec = 96000;
11672 pWF->nBlockAlign = (pWF->nChannels * pWF->wBitsPerSample) / 8;
11673 pWF->nAvgBytesPerSec = pWF->nBlockAlign * pWF->nSamplesPerSec;
11680 WORD bitsPerSample;
11684 ma_assert(pContext !=
NULL);
11685 ma_assert(pCaps !=
NULL);
11686 ma_assert(pDeviceInfo !=
NULL);
11697 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), pCaps->szPname, (
size_t)-1);
11709 if (!ma_is_guid_equal(&pCaps->NameGuid, &MA_GUID_NULL)) {
11710 wchar_t guidStrW[256];
11711 if (((MA_PFN_StringFromGUID2)pContext->win32.StringFromGUID2)(&pCaps->NameGuid, guidStrW, ma_countof(guidStrW)) > 0) {
11716 WideCharToMultiByte(CP_UTF8, 0, guidStrW, -1, guidStr,
sizeof(guidStr), 0, FALSE);
11718 ma_strcpy_s(keyStr,
sizeof(keyStr),
"SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
11719 ma_strcat_s(keyStr,
sizeof(keyStr), guidStr);
11721 if (((MA_PFN_RegOpenKeyExA)pContext->win32.RegOpenKeyExA)(HKEY_LOCAL_MACHINE, keyStr, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
11722 BYTE nameFromReg[512];
11723 DWORD nameFromRegSize =
sizeof(nameFromReg);
11724 result = ((MA_PFN_RegQueryValueExA)pContext->win32.RegQueryValueExA)(hKey,
"Name", 0,
NULL, (LPBYTE)nameFromReg, (LPDWORD)&nameFromRegSize);
11725 ((MA_PFN_RegCloseKey)pContext->win32.RegCloseKey)(hKey);
11727 if (
result == ERROR_SUCCESS) {
11730 if (ma_strcpy_s(
name,
sizeof(
name), pDeviceInfo->
name) == 0) {
11731 char* nameBeg = ma_find_last_character(
name,
'(');
11732 if (nameBeg !=
NULL) {
11733 size_t leadingLen = (nameBeg -
name);
11734 ma_strncpy_s(nameBeg + 1,
sizeof(
name) - leadingLen, (
const char*)nameFromReg, (
size_t)-1);
11737 if (leadingLen + nameFromRegSize <
sizeof(
name)-1) {
11738 ma_strcat_s(
name,
sizeof(
name),
")");
11741 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name),
name, (
size_t)-1);
11750 result = ma_get_best_info_from_formats_flags__winmm(pCaps->dwFormats, pCaps->wChannels, &bitsPerSample, &sampleRate);
11760 if (bitsPerSample == 8) {
11762 }
else if (bitsPerSample == 16) {
11764 }
else if (bitsPerSample == 24) {
11766 }
else if (bitsPerSample == 32) {
11779 ma_assert(pContext !=
NULL);
11780 ma_assert(pCaps !=
NULL);
11781 ma_assert(pDeviceInfo !=
NULL);
11783 ma_copy_memory(caps.szPname, pCaps->szPname,
sizeof(caps.szPname));
11784 caps.dwFormats = pCaps->dwFormats;
11785 caps.wChannels = pCaps->wChannels;
11786 caps.NameGuid = pCaps->NameGuid;
11787 return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
11794 ma_assert(pContext !=
NULL);
11795 ma_assert(pCaps !=
NULL);
11796 ma_assert(pDeviceInfo !=
NULL);
11798 ma_copy_memory(caps.szPname, pCaps->szPname,
sizeof(caps.szPname));
11799 caps.dwFormats = pCaps->dwFormats;
11800 caps.wChannels = pCaps->wChannels;
11801 caps.NameGuid = pCaps->NameGuid;
11802 return ma_context_get_device_info_from_WAVECAPS(pContext, &caps, pDeviceInfo);
11808 ma_assert(pContext !=
NULL);
11809 ma_assert(pID0 !=
NULL);
11810 ma_assert(pID1 !=
NULL);
11813 return pID0->winmm == pID1->winmm;
11818 UINT playbackDeviceCount;
11819 UINT captureDeviceCount;
11820 UINT iPlaybackDevice;
11821 UINT iCaptureDevice;
11823 ma_assert(pContext !=
NULL);
11824 ma_assert(callback !=
NULL);
11827 playbackDeviceCount = ((MA_PFN_waveOutGetNumDevs)pContext->winmm.waveOutGetNumDevs)();
11828 for (iPlaybackDevice = 0; iPlaybackDevice < playbackDeviceCount; ++iPlaybackDevice) {
11830 MA_WAVEOUTCAPS2A caps;
11832 ma_zero_object(&caps);
11834 result = ((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(iPlaybackDevice, (WAVEOUTCAPSA*)&caps,
sizeof(caps));
11835 if (
result == MMSYSERR_NOERROR) {
11838 ma_zero_object(&deviceInfo);
11839 deviceInfo.
id.winmm = iPlaybackDevice;
11841 if (ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, &deviceInfo) ==
MA_SUCCESS) {
11851 captureDeviceCount = ((MA_PFN_waveInGetNumDevs)pContext->winmm.waveInGetNumDevs)();
11852 for (iCaptureDevice = 0; iCaptureDevice < captureDeviceCount; ++iCaptureDevice) {
11854 MA_WAVEINCAPS2A caps;
11856 ma_zero_object(&caps);
11858 result = ((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(iCaptureDevice, (WAVEINCAPSA*)&caps,
sizeof(caps));
11859 if (
result == MMSYSERR_NOERROR) {
11862 ma_zero_object(&deviceInfo);
11863 deviceInfo.
id.winmm = iCaptureDevice;
11865 if (ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, &deviceInfo) ==
MA_SUCCESS) {
11879 UINT winMMDeviceID;
11881 ma_assert(pContext !=
NULL);
11888 if (pDeviceID !=
NULL) {
11889 winMMDeviceID = (UINT)pDeviceID->winmm;
11892 pDeviceInfo->
id.winmm = winMMDeviceID;
11896 MA_WAVEOUTCAPS2A caps;
11898 ma_zero_object(&caps);
11900 result = ((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(winMMDeviceID, (WAVEOUTCAPSA*)&caps,
sizeof(caps));
11901 if (
result == MMSYSERR_NOERROR) {
11902 return ma_context_get_device_info_from_WAVEOUTCAPS2(pContext, &caps, pDeviceInfo);
11906 MA_WAVEINCAPS2A caps;
11908 ma_zero_object(&caps);
11910 result = ((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(winMMDeviceID, (WAVEINCAPSA*)&caps,
sizeof(caps));
11911 if (
result == MMSYSERR_NOERROR) {
11912 return ma_context_get_device_info_from_WAVEINCAPS2(pContext, &caps, pDeviceInfo);
11920 void ma_device_uninit__winmm(
ma_device* pDevice)
11922 ma_assert(pDevice !=
NULL);
11925 ((MA_PFN_waveInClose)pDevice->pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
11926 CloseHandle((HANDLE)pDevice->winmm.hEventCapture);
11930 ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
11931 ((MA_PFN_waveOutClose)pDevice->pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
11932 CloseHandle((HANDLE)pDevice->winmm.hEventPlayback);
11935 ma_free(pDevice->winmm._pHeapData);
11937 ma_zero_object(&pDevice->winmm);
11942 const char* errorMsg =
"";
11946 UINT winMMDeviceIDPlayback = 0;
11947 UINT winMMDeviceIDCapture = 0;
11950 ma_assert(pDevice !=
NULL);
11951 ma_zero_object(&pDevice->winmm);
11964 if (bufferSizeInMilliseconds == 0) {
11969 if (pDevice->usingDefaultBufferSize) {
11971 bufferSizeInMilliseconds = 40 * pConfig->
periods;
11973 bufferSizeInMilliseconds = 400 * pConfig->
periods;
11993 if (pDevice->winmm.hEventCapture ==
NULL) {
11994 errorMsg =
"[WinMM] Failed to create event for fragment enqueing for the capture device.", errorCode =
MA_FAILED_TO_CREATE_EVENT;
11999 if (((MA_PFN_waveInGetDevCapsA)pContext->winmm.waveInGetDevCapsA)(winMMDeviceIDCapture, &caps,
sizeof(caps)) != MMSYSERR_NOERROR) {
12004 result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
12006 errorMsg =
"[WinMM] Could not find appropriate format for internal device.", errorCode =
result;
12010 resultMM = ((MA_PFN_waveInOpen)pDevice->pContext->winmm.waveInOpen)((LPHWAVEIN)&pDevice->winmm.hDeviceCapture, winMMDeviceIDCapture, &wf, (DWORD_PTR)pDevice->winmm.hEventCapture, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
12011 if (resultMM != MMSYSERR_NOERROR) {
12016 pDevice->capture.internalFormat = ma_format_from_WAVEFORMATEX(&wf);
12017 pDevice->capture.internalChannels = wf.nChannels;
12018 pDevice->capture.internalSampleRate = wf.nSamplesPerSec;
12020 pDevice->capture.internalPeriods = pConfig->
periods;
12030 pDevice->winmm.hEventPlayback = (
ma_handle)CreateEvent(
NULL, TRUE, TRUE,
NULL);
12031 if (pDevice->winmm.hEventPlayback ==
NULL) {
12032 errorMsg =
"[WinMM] Failed to create event for fragment enqueing for the playback device.", errorCode =
MA_FAILED_TO_CREATE_EVENT;
12037 if (((MA_PFN_waveOutGetDevCapsA)pContext->winmm.waveOutGetDevCapsA)(winMMDeviceIDPlayback, &caps,
sizeof(caps)) != MMSYSERR_NOERROR) {
12042 result = ma_formats_flags_to_WAVEFORMATEX__winmm(caps.dwFormats, caps.wChannels, &wf);
12044 errorMsg =
"[WinMM] Could not find appropriate format for internal device.", errorCode =
result;
12048 resultMM = ((MA_PFN_waveOutOpen)pContext->winmm.waveOutOpen)((LPHWAVEOUT)&pDevice->winmm.hDevicePlayback, winMMDeviceIDPlayback, &wf, (DWORD_PTR)pDevice->winmm.hEventPlayback, (DWORD_PTR)pDevice, CALLBACK_EVENT | WAVE_ALLOWSYNC);
12049 if (resultMM != MMSYSERR_NOERROR) {
12054 pDevice->playback.internalFormat = ma_format_from_WAVEFORMATEX(&wf);
12055 pDevice->playback.internalChannels = wf.nChannels;
12056 pDevice->playback.internalSampleRate = wf.nSamplesPerSec;
12058 pDevice->playback.internalPeriods = pConfig->
periods;
12069 heapSize +=
sizeof(WAVEHDR)*pDevice->capture.internalPeriods + (pDevice->capture.internalBufferSizeInFrames*ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
12072 heapSize +=
sizeof(WAVEHDR)*pDevice->playback.internalPeriods + (pDevice->playback.internalBufferSizeInFrames*ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
12076 if (pDevice->winmm._pHeapData ==
NULL) {
12077 errorMsg =
"[WinMM] Failed to allocate memory for the intermediary buffer.", errorCode =
MA_OUT_OF_MEMORY;
12081 ma_zero_memory(pDevice->winmm._pHeapData, heapSize);
12087 pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
12088 pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods));
12090 pDevice->winmm.pWAVEHDRCapture = pDevice->winmm._pHeapData;
12091 pDevice->winmm.pIntermediaryBufferCapture = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods + pDevice->playback.internalPeriods));
12095 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
12096 ma_uint32 fragmentSizeInBytes = ma_get_fragment_size_in_bytes(pDevice->capture.internalBufferSizeInFrames, pDevice->capture.internalPeriods, pDevice->capture.internalFormat, pDevice->capture.internalChannels);
12098 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferCapture + (fragmentSizeInBytes*iPeriod));
12099 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwBufferLength = fragmentSizeInBytes;
12100 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwFlags = 0L;
12101 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwLoops = 0L;
12102 ((MA_PFN_waveInPrepareHeader)pContext->winmm.waveInPrepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod],
sizeof(WAVEHDR));
12108 ((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod].dwUser = 0;
12115 pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData;
12116 pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*pDevice->playback.internalPeriods);
12118 pDevice->winmm.pWAVEHDRPlayback = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods));
12119 pDevice->winmm.pIntermediaryBufferPlayback = pDevice->winmm._pHeapData + (
sizeof(WAVEHDR)*(pDevice->capture.internalPeriods + pDevice->playback.internalPeriods)) + (pDevice->playback.internalBufferSizeInFrames*ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
12123 for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
12124 ma_uint32 fragmentSizeInBytes = ma_get_fragment_size_in_bytes(pDevice->playback.internalBufferSizeInFrames, pDevice->playback.internalPeriods, pDevice->playback.internalFormat, pDevice->playback.internalChannels);
12126 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].lpData = (LPSTR)(pDevice->winmm.pIntermediaryBufferPlayback + (fragmentSizeInBytes*iPeriod));
12127 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwBufferLength = fragmentSizeInBytes;
12128 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwFlags = 0L;
12129 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwLoops = 0L;
12130 ((MA_PFN_waveOutPrepareHeader)pContext->winmm.waveOutPrepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod],
sizeof(WAVEHDR));
12136 ((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod].dwUser = 0;
12144 if (pDevice->winmm.pWAVEHDRCapture !=
NULL) {
12146 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
12147 ((MA_PFN_waveInUnprepareHeader)pContext->winmm.waveInUnprepareHeader)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((WAVEHDR*)pDevice->winmm.pWAVEHDRCapture)[iPeriod],
sizeof(WAVEHDR));
12151 ((MA_PFN_waveInClose)pContext->winmm.waveInClose)((HWAVEIN)pDevice->winmm.hDeviceCapture);
12155 if (pDevice->winmm.pWAVEHDRCapture !=
NULL) {
12157 for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
12158 ((MA_PFN_waveOutUnprepareHeader)pContext->winmm.waveOutUnprepareHeader)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &((WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback)[iPeriod],
sizeof(WAVEHDR));
12162 ((MA_PFN_waveOutClose)pContext->winmm.waveOutClose)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
12165 ma_free(pDevice->winmm._pHeapData);
12173 ma_assert(pDevice !=
NULL);
12176 if (pDevice->winmm.hDeviceCapture ==
NULL) {
12180 resultMM = ((MA_PFN_waveInReset)pDevice->pContext->winmm.waveInReset)((HWAVEIN)pDevice->winmm.hDeviceCapture);
12181 if (resultMM != MMSYSERR_NOERROR) {
12182 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] WARNING: Failed to reset capture device.", ma_result_from_MMRESULT(resultMM));
12187 if (pDevice->winmm.hDevicePlayback ==
NULL) {
12191 resultMM = ((MA_PFN_waveOutReset)pDevice->pContext->winmm.waveOutReset)((HWAVEOUT)pDevice->winmm.hDevicePlayback);
12192 if (resultMM != MMSYSERR_NOERROR) {
12193 ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] WARNING: Failed to reset playback device.", ma_result_from_MMRESULT(resultMM));
12207 ma_assert(pDevice !=
NULL);
12208 ma_assert(pPCMFrames !=
NULL);
12210 if (pFramesWritten !=
NULL) {
12211 *pFramesWritten = 0;
12214 pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRPlayback;
12217 totalFramesWritten = 0;
12218 while (totalFramesWritten < frameCount) {
12220 if (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser == 0) {
12225 ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
12226 ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedPlayback;
12228 ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesWritten));
12229 const void* pSrc = ma_offset_ptr(pPCMFrames, totalFramesWritten*bpf);
12230 void* pDst = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].lpData, pDevice->winmm.headerFramesConsumedPlayback*bpf);
12231 ma_copy_memory(pDst, pSrc, framesToCopy*bpf);
12233 pDevice->winmm.headerFramesConsumedPlayback += framesToCopy;
12234 totalFramesWritten += framesToCopy;
12237 if (pDevice->winmm.headerFramesConsumedPlayback == (pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwBufferLength/bpf)) {
12238 pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 1;
12239 pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags &= ~WHDR_DONE;
12242 ResetEvent((HANDLE)pDevice->winmm.hEventPlayback);
12245 resultMM = ((MA_PFN_waveOutWrite)pDevice->pContext->winmm.waveOutWrite)((HWAVEOUT)pDevice->winmm.hDevicePlayback, &pWAVEHDR[pDevice->winmm.iNextHeaderPlayback],
sizeof(WAVEHDR));
12246 if (resultMM != MMSYSERR_NOERROR) {
12247 result = ma_result_from_MMRESULT(resultMM);
12253 pDevice->winmm.iNextHeaderPlayback = (pDevice->winmm.iNextHeaderPlayback + 1) % pDevice->playback.internalPeriods;
12254 pDevice->winmm.headerFramesConsumedPlayback = 0;
12258 ma_assert(totalFramesWritten <= frameCount);
12259 if (totalFramesWritten == frameCount) {
12268 if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventPlayback, INFINITE) != WAIT_OBJECT_0) {
12274 if ((pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwFlags & WHDR_DONE) != 0) {
12275 pWAVEHDR[pDevice->winmm.iNextHeaderPlayback].dwUser = 0;
12276 pDevice->winmm.headerFramesConsumedPlayback = 0;
12280 if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
12285 if (pFramesWritten !=
NULL) {
12286 *pFramesWritten = totalFramesWritten;
12299 ma_assert(pDevice !=
NULL);
12300 ma_assert(pPCMFrames !=
NULL);
12302 if (pFramesRead !=
NULL) {
12306 pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
12309 totalFramesRead = 0;
12310 while (totalFramesRead < frameCount) {
12312 if (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser == 0) {
12314 ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
12315 ma_uint32 framesRemainingInHeader = (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf) - pDevice->winmm.headerFramesConsumedCapture;
12317 ma_uint32 framesToCopy = ma_min(framesRemainingInHeader, (frameCount - totalFramesRead));
12318 const void* pSrc = ma_offset_ptr(pWAVEHDR[pDevice->winmm.iNextHeaderCapture].lpData, pDevice->winmm.headerFramesConsumedCapture*bpf);
12319 void* pDst = ma_offset_ptr(pPCMFrames, totalFramesRead*bpf);
12320 ma_copy_memory(pDst, pSrc, framesToCopy*bpf);
12322 pDevice->winmm.headerFramesConsumedCapture += framesToCopy;
12323 totalFramesRead += framesToCopy;
12326 if (pDevice->winmm.headerFramesConsumedCapture == (pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwBufferLength/bpf)) {
12327 pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 1;
12328 pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags &= ~WHDR_DONE;
12331 ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
12334 resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[pDevice->winmm.iNextHeaderCapture],
sizeof(WAVEHDR));
12335 if (resultMM != MMSYSERR_NOERROR) {
12336 result = ma_result_from_MMRESULT(resultMM);
12342 pDevice->winmm.iNextHeaderCapture = (pDevice->winmm.iNextHeaderCapture + 1) % pDevice->capture.internalPeriods;
12343 pDevice->winmm.headerFramesConsumedCapture = 0;
12347 ma_assert(totalFramesRead <= frameCount);
12348 if (totalFramesRead == frameCount) {
12357 if (WaitForSingleObject((HANDLE)pDevice->winmm.hEventCapture, INFINITE) != WAIT_OBJECT_0) {
12363 if ((pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwFlags & WHDR_DONE) != 0) {
12364 pWAVEHDR[pDevice->winmm.iNextHeaderCapture].dwUser = 0;
12365 pDevice->winmm.headerFramesConsumedCapture = 0;
12369 if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
12374 if (pFramesRead !=
NULL) {
12375 *pFramesRead = totalFramesRead;
12386 ma_assert(pDevice !=
NULL);
12394 pWAVEHDR = (WAVEHDR*)pDevice->winmm.pWAVEHDRCapture;
12397 ResetEvent((HANDLE)pDevice->winmm.hEventCapture);
12400 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
12401 resultMM = ((MA_PFN_waveInAddBuffer)pDevice->pContext->winmm.waveInAddBuffer)((HWAVEIN)pDevice->winmm.hDeviceCapture, &((LPWAVEHDR)pDevice->winmm.pWAVEHDRCapture)[iPeriod],
sizeof(WAVEHDR));
12402 if (resultMM != MMSYSERR_NOERROR) {
12403 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] Failed to attach input buffers to capture device in preparation for capture.", ma_result_from_MMRESULT(resultMM));
12407 pWAVEHDR[iPeriod].dwUser = 1;
12411 resultMM = ((MA_PFN_waveInStart)pDevice->pContext->winmm.waveInStart)((HWAVEIN)pDevice->winmm.hDeviceCapture);
12412 if (resultMM != MMSYSERR_NOERROR) {
12413 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[WinMM] Failed to start backend device.", ma_result_from_MMRESULT(resultMM));
12418 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
12419 switch (pDevice->type)
12424 ma_uint8 capturedDeviceData[8192];
12425 ma_uint8 playbackDeviceData[8192];
12426 ma_uint32 capturedDeviceDataCapInFrames =
sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
12427 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
12430 ma_uint32 periodSizeInFrames = ma_min(pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods, pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods);
12432 while (totalFramesProcessed < periodSizeInFrames) {
12433 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
12435 ma_uint32 framesToProcess = framesRemaining;
12436 if (framesToProcess > capturedDeviceDataCapInFrames) {
12437 framesToProcess = capturedDeviceDataCapInFrames;
12440 result = ma_device_read__winmm(pDevice, capturedDeviceData, framesToProcess, &framesProcessed);
12446 pDevice->capture._dspFrameCount = framesToProcess;
12447 pDevice->capture._dspFrames = capturedDeviceData;
12452 ma_uint32 capturedDataCapInFrames =
sizeof(capturedData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
12453 ma_uint32 playbackDataCapInFrames =
sizeof(playbackData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
12455 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
12457 if (capturedFramesToProcess == 0) {
12461 ma_device__on_data(pDevice, playbackData, capturedData, capturedFramesToProcess);
12464 pDevice->playback._dspFrameCount = capturedFramesToProcess;
12465 pDevice->playback._dspFrames = playbackData;
12468 if (playbackDeviceFramesCount == 0) {
12472 result = ma_device_write__winmm(pDevice, playbackDeviceData, playbackDeviceFramesCount,
NULL);
12478 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
12483 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
12494 totalFramesProcessed += framesProcessed;
12501 ma_uint8 intermediaryBuffer[8192];
12502 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
12503 ma_uint32 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
12505 while (framesReadThisPeriod < periodSizeInFrames) {
12506 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
12508 ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
12509 if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
12510 framesToReadThisIteration = intermediaryBufferSizeInFrames;
12513 result = ma_device_read__winmm(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
12519 ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
12521 framesReadThisPeriod += framesProcessed;
12528 ma_uint8 intermediaryBuffer[8192];
12529 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
12530 ma_uint32 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
12532 while (framesWrittenThisPeriod < periodSizeInFrames) {
12533 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
12535 ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
12536 if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
12537 framesToWriteThisIteration = intermediaryBufferSizeInFrames;
12540 ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
12542 result = ma_device_write__winmm(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
12548 framesWrittenThisPeriod += framesProcessed;
12560 ma_device_stop__winmm(pDevice);
12567 ma_assert(pContext !=
NULL);
12570 ma_dlclose(pContext, pContext->winmm.hWinMM);
12576 ma_assert(pContext !=
NULL);
12580 pContext->winmm.hWinMM = ma_dlopen(pContext,
"winmm.dll");
12581 if (pContext->winmm.hWinMM ==
NULL) {
12585 pContext->winmm.waveOutGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutGetNumDevs");
12586 pContext->winmm.waveOutGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutGetDevCapsA");
12587 pContext->winmm.waveOutOpen = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutOpen");
12588 pContext->winmm.waveOutClose = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutClose");
12589 pContext->winmm.waveOutPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutPrepareHeader");
12590 pContext->winmm.waveOutUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutUnprepareHeader");
12591 pContext->winmm.waveOutWrite = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutWrite");
12592 pContext->winmm.waveOutReset = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveOutReset");
12593 pContext->winmm.waveInGetNumDevs = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInGetNumDevs");
12594 pContext->winmm.waveInGetDevCapsA = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInGetDevCapsA");
12595 pContext->winmm.waveInOpen = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInOpen");
12596 pContext->winmm.waveInClose = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInClose");
12597 pContext->winmm.waveInPrepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInPrepareHeader");
12598 pContext->winmm.waveInUnprepareHeader = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInUnprepareHeader");
12599 pContext->winmm.waveInAddBuffer = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInAddBuffer");
12600 pContext->winmm.waveInStart = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInStart");
12601 pContext->winmm.waveInReset = ma_dlsym(pContext, pContext->winmm.hWinMM,
"waveInReset");
12603 pContext->
onUninit = ma_context_uninit__winmm;
12605 pContext->
onEnumDevices = ma_context_enumerate_devices__winmm;
12627 #ifdef MA_NO_RUNTIME_LINKING
12628 #include <alsa/asoundlib.h>
12629 typedef snd_pcm_uframes_t ma_snd_pcm_uframes_t;
12630 typedef snd_pcm_sframes_t ma_snd_pcm_sframes_t;
12631 typedef snd_pcm_stream_t ma_snd_pcm_stream_t;
12632 typedef snd_pcm_format_t ma_snd_pcm_format_t;
12633 typedef snd_pcm_access_t ma_snd_pcm_access_t;
12634 typedef snd_pcm_t ma_snd_pcm_t;
12635 typedef snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
12636 typedef snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
12637 typedef snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
12638 typedef snd_pcm_info_t ma_snd_pcm_info_t;
12639 typedef snd_pcm_channel_area_t ma_snd_pcm_channel_area_t;
12640 typedef snd_pcm_chmap_t ma_snd_pcm_chmap_t;
12643 #define MA_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK
12644 #define MA_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE
12647 #define MA_SND_PCM_FORMAT_UNKNOWN SND_PCM_FORMAT_UNKNOWN
12648 #define MA_SND_PCM_FORMAT_U8 SND_PCM_FORMAT_U8
12649 #define MA_SND_PCM_FORMAT_S16_LE SND_PCM_FORMAT_S16_LE
12650 #define MA_SND_PCM_FORMAT_S16_BE SND_PCM_FORMAT_S16_BE
12651 #define MA_SND_PCM_FORMAT_S24_LE SND_PCM_FORMAT_S24_LE
12652 #define MA_SND_PCM_FORMAT_S24_BE SND_PCM_FORMAT_S24_BE
12653 #define MA_SND_PCM_FORMAT_S32_LE SND_PCM_FORMAT_S32_LE
12654 #define MA_SND_PCM_FORMAT_S32_BE SND_PCM_FORMAT_S32_BE
12655 #define MA_SND_PCM_FORMAT_FLOAT_LE SND_PCM_FORMAT_FLOAT_LE
12656 #define MA_SND_PCM_FORMAT_FLOAT_BE SND_PCM_FORMAT_FLOAT_BE
12657 #define MA_SND_PCM_FORMAT_FLOAT64_LE SND_PCM_FORMAT_FLOAT64_LE
12658 #define MA_SND_PCM_FORMAT_FLOAT64_BE SND_PCM_FORMAT_FLOAT64_BE
12659 #define MA_SND_PCM_FORMAT_MU_LAW SND_PCM_FORMAT_MU_LAW
12660 #define MA_SND_PCM_FORMAT_A_LAW SND_PCM_FORMAT_A_LAW
12661 #define MA_SND_PCM_FORMAT_S24_3LE SND_PCM_FORMAT_S24_3LE
12662 #define MA_SND_PCM_FORMAT_S24_3BE SND_PCM_FORMAT_S24_3BE
12665 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED SND_PCM_ACCESS_MMAP_INTERLEAVED
12666 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED SND_PCM_ACCESS_MMAP_NONINTERLEAVED
12667 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX SND_PCM_ACCESS_MMAP_COMPLEX
12668 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED SND_PCM_ACCESS_RW_INTERLEAVED
12669 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED SND_PCM_ACCESS_RW_NONINTERLEAVED
12672 #define MA_SND_CHMAP_UNKNOWN SND_CHMAP_UNKNOWN
12673 #define MA_SND_CHMAP_NA SND_CHMAP_NA
12674 #define MA_SND_CHMAP_MONO SND_CHMAP_MONO
12675 #define MA_SND_CHMAP_FL SND_CHMAP_FL
12676 #define MA_SND_CHMAP_FR SND_CHMAP_FR
12677 #define MA_SND_CHMAP_RL SND_CHMAP_RL
12678 #define MA_SND_CHMAP_RR SND_CHMAP_RR
12679 #define MA_SND_CHMAP_FC SND_CHMAP_FC
12680 #define MA_SND_CHMAP_LFE SND_CHMAP_LFE
12681 #define MA_SND_CHMAP_SL SND_CHMAP_SL
12682 #define MA_SND_CHMAP_SR SND_CHMAP_SR
12683 #define MA_SND_CHMAP_RC SND_CHMAP_RC
12684 #define MA_SND_CHMAP_FLC SND_CHMAP_FLC
12685 #define MA_SND_CHMAP_FRC SND_CHMAP_FRC
12686 #define MA_SND_CHMAP_RLC SND_CHMAP_RLC
12687 #define MA_SND_CHMAP_RRC SND_CHMAP_RRC
12688 #define MA_SND_CHMAP_FLW SND_CHMAP_FLW
12689 #define MA_SND_CHMAP_FRW SND_CHMAP_FRW
12690 #define MA_SND_CHMAP_FLH SND_CHMAP_FLH
12691 #define MA_SND_CHMAP_FCH SND_CHMAP_FCH
12692 #define MA_SND_CHMAP_FRH SND_CHMAP_FRH
12693 #define MA_SND_CHMAP_TC SND_CHMAP_TC
12694 #define MA_SND_CHMAP_TFL SND_CHMAP_TFL
12695 #define MA_SND_CHMAP_TFR SND_CHMAP_TFR
12696 #define MA_SND_CHMAP_TFC SND_CHMAP_TFC
12697 #define MA_SND_CHMAP_TRL SND_CHMAP_TRL
12698 #define MA_SND_CHMAP_TRR SND_CHMAP_TRR
12699 #define MA_SND_CHMAP_TRC SND_CHMAP_TRC
12700 #define MA_SND_CHMAP_TFLC SND_CHMAP_TFLC
12701 #define MA_SND_CHMAP_TFRC SND_CHMAP_TFRC
12702 #define MA_SND_CHMAP_TSL SND_CHMAP_TSL
12703 #define MA_SND_CHMAP_TSR SND_CHMAP_TSR
12704 #define MA_SND_CHMAP_LLFE SND_CHMAP_LLFE
12705 #define MA_SND_CHMAP_RLFE SND_CHMAP_RLFE
12706 #define MA_SND_CHMAP_BC SND_CHMAP_BC
12707 #define MA_SND_CHMAP_BLC SND_CHMAP_BLC
12708 #define MA_SND_CHMAP_BRC SND_CHMAP_BRC
12711 #define MA_SND_PCM_NO_AUTO_RESAMPLE SND_PCM_NO_AUTO_RESAMPLE
12712 #define MA_SND_PCM_NO_AUTO_CHANNELS SND_PCM_NO_AUTO_CHANNELS
12713 #define MA_SND_PCM_NO_AUTO_FORMAT SND_PCM_NO_AUTO_FORMAT
12716 typedef unsigned long ma_snd_pcm_uframes_t;
12717 typedef long ma_snd_pcm_sframes_t;
12718 typedef int ma_snd_pcm_stream_t;
12719 typedef int ma_snd_pcm_format_t;
12720 typedef int ma_snd_pcm_access_t;
12721 typedef struct ma_snd_pcm_t ma_snd_pcm_t;
12722 typedef struct ma_snd_pcm_hw_params_t ma_snd_pcm_hw_params_t;
12723 typedef struct ma_snd_pcm_sw_params_t ma_snd_pcm_sw_params_t;
12724 typedef struct ma_snd_pcm_format_mask_t ma_snd_pcm_format_mask_t;
12725 typedef struct ma_snd_pcm_info_t ma_snd_pcm_info_t;
12729 unsigned int first;
12731 } ma_snd_pcm_channel_area_t;
12734 unsigned int channels;
12735 unsigned int pos[1];
12736 } ma_snd_pcm_chmap_t;
12739 #define MA_SND_PCM_STATE_OPEN 0
12740 #define MA_SND_PCM_STATE_SETUP 1
12741 #define MA_SND_PCM_STATE_PREPARED 2
12742 #define MA_SND_PCM_STATE_RUNNING 3
12743 #define MA_SND_PCM_STATE_XRUN 4
12744 #define MA_SND_PCM_STATE_DRAINING 5
12745 #define MA_SND_PCM_STATE_PAUSED 6
12746 #define MA_SND_PCM_STATE_SUSPENDED 7
12747 #define MA_SND_PCM_STATE_DISCONNECTED 8
12750 #define MA_SND_PCM_STREAM_PLAYBACK 0
12751 #define MA_SND_PCM_STREAM_CAPTURE 1
12754 #define MA_SND_PCM_FORMAT_UNKNOWN -1
12755 #define MA_SND_PCM_FORMAT_U8 1
12756 #define MA_SND_PCM_FORMAT_S16_LE 2
12757 #define MA_SND_PCM_FORMAT_S16_BE 3
12758 #define MA_SND_PCM_FORMAT_S24_LE 6
12759 #define MA_SND_PCM_FORMAT_S24_BE 7
12760 #define MA_SND_PCM_FORMAT_S32_LE 10
12761 #define MA_SND_PCM_FORMAT_S32_BE 11
12762 #define MA_SND_PCM_FORMAT_FLOAT_LE 14
12763 #define MA_SND_PCM_FORMAT_FLOAT_BE 15
12764 #define MA_SND_PCM_FORMAT_FLOAT64_LE 16
12765 #define MA_SND_PCM_FORMAT_FLOAT64_BE 17
12766 #define MA_SND_PCM_FORMAT_MU_LAW 20
12767 #define MA_SND_PCM_FORMAT_A_LAW 21
12768 #define MA_SND_PCM_FORMAT_S24_3LE 32
12769 #define MA_SND_PCM_FORMAT_S24_3BE 33
12772 #define MA_SND_PCM_ACCESS_MMAP_INTERLEAVED 0
12773 #define MA_SND_PCM_ACCESS_MMAP_NONINTERLEAVED 1
12774 #define MA_SND_PCM_ACCESS_MMAP_COMPLEX 2
12775 #define MA_SND_PCM_ACCESS_RW_INTERLEAVED 3
12776 #define MA_SND_PCM_ACCESS_RW_NONINTERLEAVED 4
12779 #define MA_SND_CHMAP_UNKNOWN 0
12780 #define MA_SND_CHMAP_NA 1
12781 #define MA_SND_CHMAP_MONO 2
12782 #define MA_SND_CHMAP_FL 3
12783 #define MA_SND_CHMAP_FR 4
12784 #define MA_SND_CHMAP_RL 5
12785 #define MA_SND_CHMAP_RR 6
12786 #define MA_SND_CHMAP_FC 7
12787 #define MA_SND_CHMAP_LFE 8
12788 #define MA_SND_CHMAP_SL 9
12789 #define MA_SND_CHMAP_SR 10
12790 #define MA_SND_CHMAP_RC 11
12791 #define MA_SND_CHMAP_FLC 12
12792 #define MA_SND_CHMAP_FRC 13
12793 #define MA_SND_CHMAP_RLC 14
12794 #define MA_SND_CHMAP_RRC 15
12795 #define MA_SND_CHMAP_FLW 16
12796 #define MA_SND_CHMAP_FRW 17
12797 #define MA_SND_CHMAP_FLH 18
12798 #define MA_SND_CHMAP_FCH 19
12799 #define MA_SND_CHMAP_FRH 20
12800 #define MA_SND_CHMAP_TC 21
12801 #define MA_SND_CHMAP_TFL 22
12802 #define MA_SND_CHMAP_TFR 23
12803 #define MA_SND_CHMAP_TFC 24
12804 #define MA_SND_CHMAP_TRL 25
12805 #define MA_SND_CHMAP_TRR 26
12806 #define MA_SND_CHMAP_TRC 27
12807 #define MA_SND_CHMAP_TFLC 28
12808 #define MA_SND_CHMAP_TFRC 29
12809 #define MA_SND_CHMAP_TSL 30
12810 #define MA_SND_CHMAP_TSR 31
12811 #define MA_SND_CHMAP_LLFE 32
12812 #define MA_SND_CHMAP_RLFE 33
12813 #define MA_SND_CHMAP_BC 34
12814 #define MA_SND_CHMAP_BLC 35
12815 #define MA_SND_CHMAP_BRC 36
12818 #define MA_SND_PCM_NO_AUTO_RESAMPLE 0x00010000
12819 #define MA_SND_PCM_NO_AUTO_CHANNELS 0x00020000
12820 #define MA_SND_PCM_NO_AUTO_FORMAT 0x00040000
12823 typedef int (* ma_snd_pcm_open_proc) (ma_snd_pcm_t **pcm,
const char *
name, ma_snd_pcm_stream_t
stream,
int mode);
12824 typedef int (* ma_snd_pcm_close_proc) (ma_snd_pcm_t *pcm);
12825 typedef size_t (* ma_snd_pcm_hw_params_sizeof_proc) (
void);
12826 typedef int (* ma_snd_pcm_hw_params_any_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params);
12827 typedef int (* ma_snd_pcm_hw_params_set_format_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_t
val);
12828 typedef int (* ma_snd_pcm_hw_params_set_format_first_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_t *
format);
12829 typedef void (* ma_snd_pcm_hw_params_get_format_mask_proc) (ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_mask_t *
mask);
12830 typedef int (* ma_snd_pcm_hw_params_set_channels_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int *
val);
12831 typedef int (* ma_snd_pcm_hw_params_set_rate_resample_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int val);
12832 typedef int (* ma_snd_pcm_hw_params_set_rate_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int *
val,
int *dir);
12833 typedef int (* ma_snd_pcm_hw_params_set_buffer_size_near_proc)(ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_uframes_t *
val);
12834 typedef int (* ma_snd_pcm_hw_params_set_periods_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params,
unsigned int *
val,
int *dir);
12835 typedef int (* ma_snd_pcm_hw_params_set_access_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_access_t _access);
12836 typedef int (* ma_snd_pcm_hw_params_get_format_proc) (
const ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_format_t *
format);
12837 typedef int (* ma_snd_pcm_hw_params_get_channels_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *
val);
12838 typedef int (* ma_snd_pcm_hw_params_get_channels_min_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *
val);
12839 typedef int (* ma_snd_pcm_hw_params_get_channels_max_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *
val);
12840 typedef int (* ma_snd_pcm_hw_params_get_rate_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *rate,
int *dir);
12841 typedef int (* ma_snd_pcm_hw_params_get_rate_min_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *rate,
int *dir);
12842 typedef int (* ma_snd_pcm_hw_params_get_rate_max_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *rate,
int *dir);
12843 typedef int (* ma_snd_pcm_hw_params_get_buffer_size_proc) (
const ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_uframes_t *
val);
12844 typedef int (* ma_snd_pcm_hw_params_get_periods_proc) (
const ma_snd_pcm_hw_params_t *
params,
unsigned int *
val,
int *dir);
12845 typedef int (* ma_snd_pcm_hw_params_get_access_proc) (
const ma_snd_pcm_hw_params_t *
params, ma_snd_pcm_access_t *_access);
12846 typedef int (* ma_snd_pcm_hw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *
params);
12847 typedef size_t (* ma_snd_pcm_sw_params_sizeof_proc) (
void);
12848 typedef int (* ma_snd_pcm_sw_params_current_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params);
12849 typedef int (* ma_snd_pcm_sw_params_get_boundary_proc) (ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t*
val);
12850 typedef int (* ma_snd_pcm_sw_params_set_avail_min_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t
val);
12851 typedef int (* ma_snd_pcm_sw_params_set_start_threshold_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t
val);
12852 typedef int (* ma_snd_pcm_sw_params_set_stop_threshold_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params, ma_snd_pcm_uframes_t
val);
12853 typedef int (* ma_snd_pcm_sw_params_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_sw_params_t *
params);
12854 typedef size_t (* ma_snd_pcm_format_mask_sizeof_proc) (
void);
12855 typedef int (* ma_snd_pcm_format_mask_test_proc) (
const ma_snd_pcm_format_mask_t *
mask, ma_snd_pcm_format_t
val);
12856 typedef ma_snd_pcm_chmap_t * (* ma_snd_pcm_get_chmap_proc) (ma_snd_pcm_t *pcm);
12857 typedef int (* ma_snd_pcm_state_proc) (ma_snd_pcm_t *pcm);
12858 typedef int (* ma_snd_pcm_prepare_proc) (ma_snd_pcm_t *pcm);
12859 typedef int (* ma_snd_pcm_start_proc) (ma_snd_pcm_t *pcm);
12860 typedef int (* ma_snd_pcm_drop_proc) (ma_snd_pcm_t *pcm);
12861 typedef int (* ma_snd_pcm_drain_proc) (ma_snd_pcm_t *pcm);
12862 typedef int (* ma_snd_device_name_hint_proc) (
int card,
const char *iface,
void ***hints);
12863 typedef char * (* ma_snd_device_name_get_hint_proc) (
const void *hint,
const char *
id);
12864 typedef int (* ma_snd_card_get_index_proc) (
const char *
name);
12865 typedef int (* ma_snd_device_name_free_hint_proc) (
void **hints);
12866 typedef int (* ma_snd_pcm_mmap_begin_proc) (ma_snd_pcm_t *pcm,
const ma_snd_pcm_channel_area_t **areas, ma_snd_pcm_uframes_t *
offset, ma_snd_pcm_uframes_t *frames);
12867 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_mmap_commit_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_uframes_t
offset, ma_snd_pcm_uframes_t frames);
12868 typedef int (* ma_snd_pcm_recover_proc) (ma_snd_pcm_t *pcm,
int err,
int silent);
12869 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_readi_proc) (ma_snd_pcm_t *pcm,
void *
buffer, ma_snd_pcm_uframes_t
size);
12870 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_writei_proc) (ma_snd_pcm_t *pcm,
const void *
buffer, ma_snd_pcm_uframes_t
size);
12871 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_proc) (ma_snd_pcm_t *pcm);
12872 typedef ma_snd_pcm_sframes_t (* ma_snd_pcm_avail_update_proc) (ma_snd_pcm_t *pcm);
12873 typedef int (* ma_snd_pcm_wait_proc) (ma_snd_pcm_t *pcm,
int timeout);
12874 typedef int (* ma_snd_pcm_info_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_info_t* info);
12875 typedef size_t (* ma_snd_pcm_info_sizeof_proc) ();
12876 typedef const char* (* ma_snd_pcm_info_get_name_proc) (
const ma_snd_pcm_info_t* info);
12877 typedef int (* ma_snd_config_update_free_global_proc) ();
12880 const char* g_maCommonDeviceNamesALSA[] = {
12888 const char* g_maBlacklistedPlaybackDeviceNamesALSA[] = {
12893 const char* g_maBlacklistedCaptureDeviceNamesALSA[] = {
12906 } g_maDefaultBufferSizeScalesALSA[] = {
12907 {
"bcm2835 IEC958/HDMI", 2.0f},
12908 {
"bcm2835 ALSA", 2.0f}
12911 float ma_find_default_buffer_size_scale__alsa(
const char* deviceName)
12915 if (deviceName ==
NULL) {
12919 for (i = 0; i < ma_countof(g_maDefaultBufferSizeScalesALSA); ++i) {
12920 if (strstr(g_maDefaultBufferSizeScalesALSA[i].
name, deviceName) !=
NULL) {
12921 return g_maDefaultBufferSizeScalesALSA[i].scale;
12928 ma_snd_pcm_format_t ma_convert_ma_format_to_alsa_format(
ma_format format)
12930 ma_snd_pcm_format_t ALSAFormats[] = {
12931 MA_SND_PCM_FORMAT_UNKNOWN,
12932 MA_SND_PCM_FORMAT_U8,
12933 MA_SND_PCM_FORMAT_S16_LE,
12934 MA_SND_PCM_FORMAT_S24_3LE,
12935 MA_SND_PCM_FORMAT_S32_LE,
12936 MA_SND_PCM_FORMAT_FLOAT_LE
12939 if (ma_is_big_endian()) {
12940 ALSAFormats[0] = MA_SND_PCM_FORMAT_UNKNOWN;
12941 ALSAFormats[1] = MA_SND_PCM_FORMAT_U8;
12942 ALSAFormats[2] = MA_SND_PCM_FORMAT_S16_BE;
12943 ALSAFormats[3] = MA_SND_PCM_FORMAT_S24_3BE;
12944 ALSAFormats[4] = MA_SND_PCM_FORMAT_S32_BE;
12945 ALSAFormats[5] = MA_SND_PCM_FORMAT_FLOAT_BE;
12948 return ALSAFormats[
format];
12951 ma_format ma_format_from_alsa(ma_snd_pcm_format_t formatALSA)
12953 if (ma_is_little_endian()) {
12954 switch (formatALSA) {
12962 switch (formatALSA) {
12972 switch (formatALSA) {
12978 ma_channel ma_convert_alsa_channel_position_to_ma_channel(
unsigned int alsaChannelPos)
12980 switch (alsaChannelPos)
12994 case MA_SND_CHMAP_RLC:
return 0;
12995 case MA_SND_CHMAP_RRC:
return 0;
12996 case MA_SND_CHMAP_FLW:
return 0;
12997 case MA_SND_CHMAP_FRW:
return 0;
12998 case MA_SND_CHMAP_FLH:
return 0;
12999 case MA_SND_CHMAP_FCH:
return 0;
13000 case MA_SND_CHMAP_FRH:
return 0;
13017 for (iName = 0; iName < ma_countof(g_maCommonDeviceNamesALSA); ++iName) {
13018 if (ma_strcmp(
name, g_maCommonDeviceNamesALSA[iName]) == 0) {
13027 ma_bool32 ma_is_playback_device_blacklisted__alsa(
const char*
name)
13030 for (iName = 0; iName < ma_countof(g_maBlacklistedPlaybackDeviceNamesALSA); ++iName) {
13031 if (ma_strcmp(
name, g_maBlacklistedPlaybackDeviceNamesALSA[iName]) == 0) {
13039 ma_bool32 ma_is_capture_device_blacklisted__alsa(
const char*
name)
13042 for (iName = 0; iName < ma_countof(g_maBlacklistedCaptureDeviceNamesALSA); ++iName) {
13043 if (ma_strcmp(
name, g_maBlacklistedCaptureDeviceNamesALSA[iName]) == 0) {
13054 return ma_is_playback_device_blacklisted__alsa(
name);
13056 return ma_is_capture_device_blacklisted__alsa(
name);
13061 const char* ma_find_char(
const char* str,
char c,
int*
index)
13065 if (str[i] ==
'\0') {
13083 ma_bool32 ma_is_device_name_in_hw_format__alsa(
const char* hwid)
13091 if (hwid ==
NULL) {
13095 if (hwid[0] !=
'h' || hwid[1] !=
'w' || hwid[2] !=
':') {
13101 dev = ma_find_char(hwid,
',', &commaPos);
13109 for (i = 0; i < commaPos; ++i) {
13110 if (hwid[i] <
'0' || hwid[i] >
'9') {
13117 while (dev[i] !=
'\0') {
13118 if (dev[i] <
'0' || dev[i] >
'9') {
13127 int ma_convert_device_name_to_hw_format__alsa(
ma_context* pContext,
char*
dst,
size_t dstSize,
const char*
src)
13150 if (ma_is_device_name_in_hw_format__alsa(
src)) {
13151 return ma_strcpy_s(
dst, dstSize,
src);
13154 src = ma_find_char(
src,
':', &colonPos);
13159 dev = ma_find_char(
src,
',', &commaPos);
13162 ma_strncpy_s(card,
sizeof(card),
src+6, (
size_t)-1);
13165 ma_strncpy_s(card,
sizeof(card),
src+6, commaPos-6);
13168 cardIndex = ((ma_snd_card_get_index_proc)pContext->alsa.snd_card_get_index)(card);
13169 if (cardIndex < 0) {
13177 dst[0] =
'h';
dst[1] =
'w';
dst[2] =
':';
13178 if (ma_itoa_s(cardIndex,
dst+3, dstSize-3, 10) != 0) {
13181 if (ma_strcat_s(
dst, dstSize,
",") != 0) {
13184 if (ma_strcat_s(
dst, dstSize, dev) != 0) {
13195 ma_assert(pHWID !=
NULL);
13197 for (i = 0; i <
count; ++i) {
13198 if (ma_strcmp(pUniqueIDs[i].alsa, pHWID) == 0) {
13209 ma_snd_pcm_t* pPCM;
13210 ma_snd_pcm_stream_t
stream;
13213 ma_assert(pContext !=
NULL);
13214 ma_assert(ppPCM !=
NULL);
13220 openMode = MA_SND_PCM_NO_AUTO_RESAMPLE | MA_SND_PCM_NO_AUTO_CHANNELS | MA_SND_PCM_NO_AUTO_FORMAT;
13222 if (pDeviceID ==
NULL) {
13230 const char* defaultDeviceNames[] = {
13241 defaultDeviceNames[1] =
"hw";
13242 defaultDeviceNames[2] =
"hw:0";
13243 defaultDeviceNames[3] =
"hw:0,0";
13246 defaultDeviceNames[1] =
"dmix";
13247 defaultDeviceNames[2] =
"dmix:0";
13248 defaultDeviceNames[3] =
"dmix:0,0";
13250 defaultDeviceNames[1] =
"dsnoop";
13251 defaultDeviceNames[2] =
"dsnoop:0";
13252 defaultDeviceNames[3] =
"dsnoop:0,0";
13254 defaultDeviceNames[4] =
"hw";
13255 defaultDeviceNames[5] =
"hw:0";
13256 defaultDeviceNames[6] =
"hw:0,0";
13260 for (i = 0; i < ma_countof(defaultDeviceNames); ++i) {
13261 if (defaultDeviceNames[i] !=
NULL && defaultDeviceNames[i][0] !=
'\0') {
13262 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, defaultDeviceNames[i],
stream, openMode) == 0) {
13269 if (!isDeviceOpen) {
13285 if (deviceID.alsa[0] !=
':') {
13287 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, deviceID.alsa,
stream, openMode) == 0) {
13294 if (deviceID.alsa[1] ==
'\0') {
13295 deviceID.alsa[0] =
'\0';
13300 ma_strcpy_s(hwid,
sizeof(hwid),
"dmix");
13302 ma_strcpy_s(hwid,
sizeof(hwid),
"dsnoop");
13305 if (ma_strcat_s(hwid,
sizeof(hwid), deviceID.alsa) == 0) {
13306 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid,
stream, openMode) == 0) {
13313 if (!isDeviceOpen) {
13314 ma_strcpy_s(hwid,
sizeof(hwid),
"hw");
13315 if (ma_strcat_s(hwid,
sizeof(hwid), deviceID.alsa) == 0) {
13316 if (((ma_snd_pcm_open_proc)pContext->alsa.snd_pcm_open)(&pPCM, hwid,
stream, openMode) == 0) {
13323 if (!isDeviceOpen) {
13335 ma_assert(pContext !=
NULL);
13336 ma_assert(pID0 !=
NULL);
13337 ma_assert(pID1 !=
NULL);
13340 return ma_strcmp(pID0->alsa, pID1->alsa) == 0;
13346 char** ppDeviceHints;
13349 char** ppNextDeviceHint;
13351 ma_assert(pContext !=
NULL);
13352 ma_assert(callback !=
NULL);
13356 if (((ma_snd_device_name_hint_proc)pContext->alsa.snd_device_name_hint)(-1,
"pcm", (
void***)&ppDeviceHints) < 0) {
13361 ppNextDeviceHint = ppDeviceHints;
13362 while (*ppNextDeviceHint !=
NULL) {
13363 char* NAME = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"NAME");
13364 char* DESC = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"DESC");
13365 char* IOID = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"IOID");
13368 char hwid[
sizeof(pUniqueIDs->alsa)];
13371 if ((IOID ==
NULL || ma_strcmp(IOID,
"Output") == 0)) {
13374 if ((IOID !=
NULL && ma_strcmp(IOID,
"Input" ) == 0)) {
13378 if (NAME !=
NULL) {
13379 if (pContext->alsa.useVerboseDeviceEnumeration) {
13381 ma_strncpy_s(hwid,
sizeof(hwid), NAME, (
size_t)-1);
13384 if (ma_convert_device_name_to_hw_format__alsa(pContext, hwid,
sizeof(hwid), NAME) == 0) {
13392 char*
src = hwid+2;
13393 while ((*
dst++ = *
src++));
13396 ma_strncpy_s(hwid,
sizeof(hwid), NAME, (
size_t)-1);
13399 if (ma_does_id_exist_in_list__alsa(pUniqueIDs, uniqueIDCount, hwid)) {
13404 if (pNewUniqueIDs ==
NULL) {
13408 pUniqueIDs = pNewUniqueIDs;
13409 ma_copy_memory(pUniqueIDs[uniqueIDCount].alsa, hwid,
sizeof(hwid));
13410 uniqueIDCount += 1;
13414 ma_zero_memory(hwid,
sizeof(hwid));
13417 ma_zero_object(&deviceInfo);
13418 ma_strncpy_s(deviceInfo.id.alsa,
sizeof(deviceInfo.id.alsa), hwid, (
size_t)-1);
13431 if (DESC !=
NULL) {
13433 const char* line2 = ma_find_char(DESC,
'\n', &lfPos);
13434 if (line2 !=
NULL) {
13437 if (pContext->alsa.useVerboseDeviceEnumeration) {
13439 ma_strncpy_s(deviceInfo.name,
sizeof(deviceInfo.name), DESC, lfPos);
13440 ma_strcat_s (deviceInfo.name,
sizeof(deviceInfo.name),
" (");
13441 ma_strcat_s (deviceInfo.name,
sizeof(deviceInfo.name), line2);
13442 ma_strcat_s (deviceInfo.name,
sizeof(deviceInfo.name),
")");
13445 ma_strncpy_s(deviceInfo.name,
sizeof(deviceInfo.name), DESC, lfPos);
13449 ma_strncpy_s(deviceInfo.name,
sizeof(deviceInfo.name), DESC, (
size_t)-1);
13453 if (!ma_is_device_blacklisted__alsa(deviceType, NAME)) {
13454 cbResult = callback(pContext, deviceType, &deviceInfo, pUserData);
13462 if (ma_is_common_device_name__alsa(NAME)) {
13464 if (!ma_is_capture_device_blacklisted__alsa(NAME)) {
13468 if (!ma_is_playback_device_blacklisted__alsa(NAME)) {
13483 ppNextDeviceHint += 1;
13486 if (stopEnumeration) {
13492 ((ma_snd_device_name_free_hint_proc)pContext->alsa.snd_device_name_free_hint)((
void**)ppDeviceHints);
13507 } ma_context_get_device_info_enum_callback_data__alsa;
13511 ma_context_get_device_info_enum_callback_data__alsa* pData = (ma_context_get_device_info_enum_callback_data__alsa*)pUserData;
13512 ma_assert(pData !=
NULL);
13514 if (pData->pDeviceID ==
NULL && ma_strcmp(pDeviceInfo->
id.alsa,
"default") == 0) {
13515 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pDeviceInfo->
name, (
size_t)-1);
13516 pData->foundDevice =
MA_TRUE;
13518 if (pData->deviceType == deviceType && ma_context_is_device_id_equal__alsa(pContext, pData->pDeviceID, &pDeviceInfo->
id)) {
13519 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pDeviceInfo->
name, (
size_t)-1);
13520 pData->foundDevice =
MA_TRUE;
13525 return !pData->foundDevice;
13530 ma_context_get_device_info_enum_callback_data__alsa
data;
13532 ma_snd_pcm_t* pPCM;
13533 ma_snd_pcm_hw_params_t* pHWParams;
13534 ma_snd_pcm_format_mask_t* pFormatMask;
13535 int sampleRateDir = 0;
13537 ma_assert(pContext !=
NULL);
13540 data.deviceType = deviceType;
13541 data.pDeviceID = pDeviceID;
13542 data.shareMode = shareMode;
13543 data.pDeviceInfo = pDeviceInfo;
13545 result = ma_context_enumerate_devices__alsa(pContext, ma_context_get_device_info_enum_callback__alsa, &
data);
13550 if (!
data.foundDevice) {
13555 result = ma_context_open_pcm__alsa(pContext, shareMode, deviceType, pDeviceID, &pPCM);
13561 pHWParams = (ma_snd_pcm_hw_params_t*)calloc(1, ((ma_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
13562 if (pHWParams ==
NULL) {
13566 if (((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams) < 0) {
13570 ((ma_snd_pcm_hw_params_get_channels_min_proc)pContext->alsa.snd_pcm_hw_params_get_channels_min)(pHWParams, &pDeviceInfo->
minChannels);
13571 ((ma_snd_pcm_hw_params_get_channels_max_proc)pContext->alsa.snd_pcm_hw_params_get_channels_max)(pHWParams, &pDeviceInfo->
maxChannels);
13572 ((ma_snd_pcm_hw_params_get_rate_min_proc)pContext->alsa.snd_pcm_hw_params_get_rate_min)(pHWParams, &pDeviceInfo->
minSampleRate, &sampleRateDir);
13573 ((ma_snd_pcm_hw_params_get_rate_max_proc)pContext->alsa.snd_pcm_hw_params_get_rate_max)(pHWParams, &pDeviceInfo->
maxSampleRate, &sampleRateDir);
13576 pFormatMask = (ma_snd_pcm_format_mask_t*)calloc(1, ((ma_snd_pcm_format_mask_sizeof_proc)pContext->alsa.snd_pcm_format_mask_sizeof)());
13577 if (pFormatMask ==
NULL) {
13581 ((ma_snd_pcm_hw_params_get_format_mask_proc)pContext->alsa.snd_pcm_hw_params_get_format_mask)(pHWParams, pFormatMask);
13584 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_U8)) {
13587 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_S16_LE)) {
13590 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_S24_3LE)) {
13593 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_S32_LE)) {
13596 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, MA_SND_PCM_FORMAT_FLOAT_LE)) {
13603 ((ma_snd_pcm_close_proc)pContext->alsa.snd_pcm_close)(pPCM);
13617 ma_assert(pDevice !=
NULL);
13619 if (pRequiresRestart) *pRequiresRestart =
MA_FALSE;
13622 ma_uint32 periodSizeInFrames = pDevice->bufferSizeInFrames / pDevice->periods;
13623 while (!pDevice->alsa.breakFromMainLoop) {
13624 ma_snd_pcm_sframes_t framesAvailable = ((ma_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((ma_snd_pcm_t*)pDevice->alsa.pPCM);
13625 if (framesAvailable < 0) {
13626 if (framesAvailable == -EPIPE) {
13627 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, framesAvailable,
MA_TRUE) < 0) {
13632 if (pRequiresRestart) {
13637 framesAvailable = ((ma_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((ma_snd_pcm_t*)pDevice->alsa.pPCM);
13638 if (framesAvailable < 0) {
13644 if (framesAvailable >= periodSizeInFrames) {
13645 return periodSizeInFrames;
13648 if (framesAvailable < periodSizeInFrames) {
13650 int waitResult = ((ma_snd_pcm_wait_proc)pDevice->pContext->alsa.snd_pcm_wait)((ma_snd_pcm_t*)pDevice->alsa.pPCM, -1);
13651 if (waitResult < 0) {
13652 if (waitResult == -EPIPE) {
13653 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, waitResult,
MA_TRUE) < 0) {
13658 if (pRequiresRestart) {
13667 ma_snd_pcm_sframes_t framesAvailable = ((ma_snd_pcm_avail_update_proc)pDevice->pContext->alsa.snd_pcm_avail_update)((ma_snd_pcm_t*)pDevice->alsa.pPCM);
13668 if (framesAvailable < 0) {
13672 return framesAvailable;
13677 ma_assert(pDevice !=
NULL);
13681 if (pDevice->alsa.breakFromMainLoop) {
13685 if (pDevice->alsa.isUsingMMap) {
13688 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice, &requiresRestart);
13689 if (framesAvailable == 0) {
13694 if (pDevice->alsa.breakFromMainLoop) {
13698 const ma_snd_pcm_channel_area_t* pAreas;
13699 ma_snd_pcm_uframes_t mappedOffset;
13700 ma_snd_pcm_uframes_t mappedFrames = framesAvailable;
13701 while (framesAvailable > 0) {
13702 int result = ((ma_snd_pcm_mmap_begin_proc)pDevice->pContext->alsa.snd_pcm_mmap_begin)((ma_snd_pcm_t*)pDevice->alsa.pPCM, &pAreas, &mappedOffset, &mappedFrames);
13707 if (mappedFrames > 0) {
13708 void* pBuffer = (
ma_uint8*)pAreas[0].
addr + ((pAreas[0].
first + (mappedOffset * pAreas[0].step)) / 8);
13709 ma_device__read_frames_from_client(pDevice, mappedFrames, pBuffer);
13712 result = ((ma_snd_pcm_mmap_commit_proc)pDevice->pContext->alsa.snd_pcm_mmap_commit)((ma_snd_pcm_t*)pDevice->alsa.pPCM, mappedOffset, mappedFrames);
13713 if (
result < 0 || (ma_snd_pcm_uframes_t)
result != mappedFrames) {
13714 ((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM,
result,
MA_TRUE);
13718 if (requiresRestart) {
13719 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
13724 if (framesAvailable >= mappedFrames) {
13725 framesAvailable -= mappedFrames;
13727 framesAvailable = 0;
13732 while (!pDevice->alsa.breakFromMainLoop) {
13733 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice,
NULL);
13734 if (framesAvailable == 0) {
13739 if (pDevice->alsa.breakFromMainLoop) {
13743 ma_device__read_frames_from_client(pDevice, framesAvailable, pDevice->alsa.pIntermediaryBuffer);
13745 ma_snd_pcm_sframes_t framesWritten = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
13746 if (framesWritten < 0) {
13747 if (framesWritten == -EAGAIN) {
13749 }
else if (framesWritten == -EPIPE) {
13751 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, framesWritten,
MA_TRUE) < 0) {
13756 framesWritten = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
13757 if (framesWritten < 0) {
13778 ma_assert(pDevice !=
NULL);
13782 if (pDevice->alsa.breakFromMainLoop) {
13787 void* pBuffer =
NULL;
13788 if (pDevice->alsa.pIntermediaryBuffer ==
NULL) {
13791 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice, &requiresRestart);
13792 if (framesAvailable == 0) {
13796 const ma_snd_pcm_channel_area_t* pAreas;
13797 ma_snd_pcm_uframes_t mappedOffset;
13798 ma_snd_pcm_uframes_t mappedFrames = framesAvailable;
13799 while (framesAvailable > 0) {
13800 int result = ((ma_snd_pcm_mmap_begin_proc)pDevice->pContext->alsa.snd_pcm_mmap_begin)((ma_snd_pcm_t*)pDevice->alsa.pPCM, &pAreas, &mappedOffset, &mappedFrames);
13805 if (mappedFrames > 0) {
13806 void* pBuffer = (
ma_uint8*)pAreas[0].
addr + ((pAreas[0].
first + (mappedOffset * pAreas[0].step)) / 8);
13807 ma_device__send_frames_to_client(pDevice, mappedFrames, pBuffer);
13810 result = ((ma_snd_pcm_mmap_commit_proc)pDevice->pContext->alsa.snd_pcm_mmap_commit)((ma_snd_pcm_t*)pDevice->alsa.pPCM, mappedOffset, mappedFrames);
13811 if (
result < 0 || (ma_snd_pcm_uframes_t)
result != mappedFrames) {
13812 ((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM,
result,
MA_TRUE);
13816 if (requiresRestart) {
13817 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
13822 if (framesAvailable >= mappedFrames) {
13823 framesAvailable -= mappedFrames;
13825 framesAvailable = 0;
13830 ma_snd_pcm_sframes_t framesRead = 0;
13831 while (!pDevice->alsa.breakFromMainLoop) {
13832 ma_uint32 framesAvailable = ma_device__wait_for_frames__alsa(pDevice,
NULL);
13833 if (framesAvailable == 0) {
13837 framesRead = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
13838 if (framesRead < 0) {
13839 if (framesRead == -EAGAIN) {
13841 }
else if (framesRead == -EPIPE) {
13843 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCM, framesRead,
MA_TRUE) < 0) {
13848 framesRead = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCM, pDevice->alsa.pIntermediaryBuffer, framesAvailable);
13849 if (framesRead < 0) {
13863 framesToSend = framesRead;
13864 pBuffer = pDevice->alsa.pIntermediaryBuffer;
13867 if (framesToSend > 0) {
13868 ma_device__send_frames_to_client(pDevice, framesToSend, pBuffer);
13875 void ma_device_uninit__alsa(
ma_device* pDevice)
13877 ma_assert(pDevice !=
NULL);
13879 if ((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) {
13880 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
13883 if ((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) {
13884 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
13891 ma_snd_pcm_t* pPCM;
13893 ma_snd_pcm_format_t formatALSA;
13902 ma_snd_pcm_hw_params_t* pHWParams;
13903 ma_snd_pcm_sw_params_t* pSWParams;
13904 ma_snd_pcm_uframes_t bufferBoundary;
13905 float bufferSizeScaleFactor;
13907 ma_assert(pContext !=
NULL);
13908 ma_assert(pConfig !=
NULL);
13910 ma_assert(pDevice !=
NULL);
13916 result = ma_context_open_pcm__alsa(pContext, shareMode, deviceType, pDeviceID, &pPCM);
13922 bufferSizeScaleFactor = 1;
13923 if (pDevice->usingDefaultBufferSize) {
13924 ma_snd_pcm_info_t* pInfo = (ma_snd_pcm_info_t*)calloc(1, ((ma_snd_pcm_info_sizeof_proc)pContext->alsa.snd_pcm_info_sizeof)());
13925 if (pInfo ==
NULL) {
13930 if (((ma_snd_pcm_info_proc)pContext->alsa.snd_pcm_info)(pPCM, pInfo) == 0) {
13931 const char* deviceName = ((ma_snd_pcm_info_get_name_proc)pContext->alsa.snd_pcm_info_get_name)(pInfo);
13932 if (deviceName !=
NULL) {
13933 if (ma_strcmp(deviceName,
"default") == 0) {
13934 char** ppDeviceHints;
13935 char** ppNextDeviceHint;
13938 if (((ma_snd_device_name_hint_proc)pContext->alsa.snd_device_name_hint)(-1,
"pcm", (
void***)&ppDeviceHints) < 0) {
13943 ppNextDeviceHint = ppDeviceHints;
13944 while (*ppNextDeviceHint !=
NULL) {
13945 char* NAME = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"NAME");
13946 char* DESC = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"DESC");
13947 char* IOID = ((ma_snd_device_name_get_hint_proc)pContext->alsa.snd_device_name_get_hint)(*ppNextDeviceHint,
"IOID");
13952 if (ma_strcmp(NAME, deviceName) == 0) {
13953 bufferSizeScaleFactor = ma_find_default_buffer_size_scale__alsa(DESC);
13961 ppNextDeviceHint += 1;
13968 ((ma_snd_device_name_free_hint_proc)pContext->alsa.snd_device_name_free_hint)((
void**)ppDeviceHints);
13970 bufferSizeScaleFactor = ma_find_default_buffer_size_scale__alsa(deviceName);
13980 pHWParams = (ma_snd_pcm_hw_params_t*)calloc(1, ((ma_snd_pcm_hw_params_sizeof_proc)pContext->alsa.snd_pcm_hw_params_sizeof)());
13981 if (pHWParams ==
NULL) {
13985 if (((ma_snd_pcm_hw_params_any_proc)pContext->alsa.snd_pcm_hw_params_any)(pPCM, pHWParams) < 0) {
13987 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
13995 if (!pConfig->
alsa.
noMMap && ma_device__is_async(pDevice)) {
13996 if (((ma_snd_pcm_hw_params_set_access_proc)pContext->alsa.snd_pcm_hw_params_set_access)(pPCM, pHWParams, MA_SND_PCM_ACCESS_MMAP_INTERLEAVED) == 0) {
13997 pDevice->alsa.isUsingMMap =
MA_TRUE;
14003 if (!isUsingMMap) {
14004 if (((ma_snd_pcm_hw_params_set_access_proc)pContext->alsa.snd_pcm_hw_params_set_access)(pPCM, pHWParams, MA_SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
14006 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14007 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[ALSA] Failed to set access mode to neither SND_PCM_ACCESS_MMAP_INTERLEAVED nor SND_PCM_ACCESS_RW_INTERLEAVED. snd_pcm_hw_params_set_access() failed.",
MA_FORMAT_NOT_SUPPORTED);
14018 ma_snd_pcm_format_mask_t* pFormatMask;
14021 pFormatMask = (ma_snd_pcm_format_mask_t*)calloc(1, ((ma_snd_pcm_format_mask_sizeof_proc)pContext->alsa.snd_pcm_format_mask_sizeof)());
14022 if (pFormatMask ==
NULL) {
14024 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14028 ((ma_snd_pcm_hw_params_get_format_mask_proc)pContext->alsa.snd_pcm_hw_params_get_format_mask)(pHWParams, pFormatMask);
14034 if (!((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, formatALSA)) {
14038 ma_snd_pcm_format_t preferredFormatsALSA[] = {
14039 MA_SND_PCM_FORMAT_S16_LE,
14040 MA_SND_PCM_FORMAT_FLOAT_LE,
14041 MA_SND_PCM_FORMAT_S32_LE,
14042 MA_SND_PCM_FORMAT_S24_3LE,
14043 MA_SND_PCM_FORMAT_U8
14046 if (ma_is_big_endian()) {
14047 preferredFormatsALSA[0] = MA_SND_PCM_FORMAT_S16_BE;
14048 preferredFormatsALSA[1] = MA_SND_PCM_FORMAT_FLOAT_BE;
14049 preferredFormatsALSA[2] = MA_SND_PCM_FORMAT_S32_BE;
14050 preferredFormatsALSA[3] = MA_SND_PCM_FORMAT_S24_3BE;
14051 preferredFormatsALSA[4] = MA_SND_PCM_FORMAT_U8;
14054 formatALSA = MA_SND_PCM_FORMAT_UNKNOWN;
14055 for (i = 0; i < (
sizeof(preferredFormatsALSA) /
sizeof(preferredFormatsALSA[0])); ++i) {
14056 if (((ma_snd_pcm_format_mask_test_proc)pContext->alsa.snd_pcm_format_mask_test)(pFormatMask, preferredFormatsALSA[i])) {
14057 formatALSA = preferredFormatsALSA[i];
14062 if (formatALSA == MA_SND_PCM_FORMAT_UNKNOWN) {
14064 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14070 pFormatMask =
NULL;
14072 if (((ma_snd_pcm_hw_params_set_format_proc)pContext->alsa.snd_pcm_hw_params_set_format)(pPCM, pHWParams, formatALSA) < 0) {
14074 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14078 internalFormat = ma_format_from_alsa(formatALSA);
14081 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14089 if (((ma_snd_pcm_hw_params_set_channels_near_proc)pContext->alsa.snd_pcm_hw_params_set_channels_near)(pPCM, pHWParams, &channels) < 0) {
14091 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14094 internalChannels = (
ma_uint32)channels;
14099 unsigned int sampleRate;
14118 ((ma_snd_pcm_hw_params_set_rate_resample_proc)pContext->alsa.snd_pcm_hw_params_set_rate_resample)(pPCM, pHWParams, 0);
14121 if (((ma_snd_pcm_hw_params_set_rate_near_proc)pContext->alsa.snd_pcm_hw_params_set_rate_near)(pPCM, pHWParams, &sampleRate, 0) < 0) {
14123 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14126 internalSampleRate = (
ma_uint32)sampleRate;
14132 if (actualBufferSizeInFrames == 0) {
14136 if (((ma_snd_pcm_hw_params_set_buffer_size_near_proc)pContext->alsa.snd_pcm_hw_params_set_buffer_size_near)(pPCM, pHWParams, &actualBufferSizeInFrames) < 0) {
14138 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14141 internalBufferSizeInFrames = actualBufferSizeInFrames;
14147 if (((ma_snd_pcm_hw_params_set_periods_near_proc)pContext->alsa.snd_pcm_hw_params_set_periods_near)(pPCM, pHWParams, &periods,
NULL) < 0) {
14149 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14152 internalPeriods = periods;
14156 if (((ma_snd_pcm_hw_params_proc)pContext->alsa.snd_pcm_hw_params)(pPCM, pHWParams) < 0) {
14158 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14167 pSWParams = (ma_snd_pcm_sw_params_t*)calloc(1, ((ma_snd_pcm_sw_params_sizeof_proc)pContext->alsa.snd_pcm_sw_params_sizeof)());
14168 if (pSWParams ==
NULL) {
14169 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14173 if (((ma_snd_pcm_sw_params_current_proc)pContext->alsa.snd_pcm_sw_params_current)(pPCM, pSWParams) != 0) {
14175 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14179 if (((ma_snd_pcm_sw_params_set_avail_min_proc)pContext->alsa.snd_pcm_sw_params_set_avail_min)(pPCM, pSWParams, ma_prev_power_of_2(internalBufferSizeInFrames/internalPeriods)) != 0) {
14181 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14185 if (((ma_snd_pcm_sw_params_get_boundary_proc)pContext->alsa.snd_pcm_sw_params_get_boundary)(pSWParams, &bufferBoundary) < 0) {
14186 bufferBoundary = internalBufferSizeInFrames;
14196 if (((ma_snd_pcm_sw_params_set_start_threshold_proc)pContext->alsa.snd_pcm_sw_params_set_start_threshold)(pPCM, pSWParams, (internalBufferSizeInFrames/internalPeriods)*2) != 0) {
14198 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14201 if (((ma_snd_pcm_sw_params_set_stop_threshold_proc)pContext->alsa.snd_pcm_sw_params_set_stop_threshold)(pPCM, pSWParams, bufferBoundary) != 0) {
14203 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14208 if (((ma_snd_pcm_sw_params_proc)pContext->alsa.snd_pcm_sw_params)(pPCM, pSWParams) != 0) {
14210 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14220 ma_snd_pcm_chmap_t* pChmap = ((ma_snd_pcm_get_chmap_proc)pContext->alsa.snd_pcm_get_chmap)(pPCM);
14221 if (pChmap !=
NULL) {
14225 if (pChmap->channels >= internalChannels) {
14227 for (iChannel = 0; iChannel < internalChannels; ++iChannel) {
14228 internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
14243 for (iChannel = 0; iChannel < pChmap->channels; ++iChannel) {
14244 internalChannelMap[iChannel] = ma_convert_alsa_channel_position_to_ma_channel(pChmap->pos[iChannel]);
14248 for (i = 0; i < internalChannels && isValid; ++i) {
14250 for (j = i+1; j < internalChannels; ++j) {
14251 if (internalChannelMap[i] == internalChannelMap[j]) {
14274 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)(pPCM) < 0) {
14275 ((ma_snd_pcm_close_proc)pDevice->pContext->alsa.snd_pcm_close)(pPCM);
14281 pDevice->alsa.pPCMCapture = (
ma_ptr)pPCM;
14282 pDevice->alsa.isUsingMMapCapture = isUsingMMap;
14283 pDevice->capture.internalFormat = internalFormat;
14284 pDevice->capture.internalChannels = internalChannels;
14285 pDevice->capture.internalSampleRate = internalSampleRate;
14286 ma_channel_map_copy(pDevice->capture.internalChannelMap, internalChannelMap, internalChannels);
14287 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
14288 pDevice->capture.internalPeriods = internalPeriods;
14290 pDevice->alsa.pPCMPlayback = (
ma_ptr)pPCM;
14291 pDevice->alsa.isUsingMMapPlayback = isUsingMMap;
14292 pDevice->playback.internalFormat = internalFormat;
14293 pDevice->playback.internalChannels = internalChannels;
14294 pDevice->playback.internalSampleRate = internalSampleRate;
14295 ma_channel_map_copy(pDevice->playback.internalChannelMap, internalChannelMap, internalChannels);
14296 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
14297 pDevice->playback.internalPeriods = internalPeriods;
14305 ma_assert(pDevice !=
NULL);
14307 ma_zero_object(&pDevice->alsa);
14333 ma_assert(pDevice !=
NULL);
14336 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
14345 if (!ma_device_read_from_client_and_write__alsa(pDevice)) {
14350 if (pDevice->alsa.isUsingMMap) {
14351 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
14356 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCM) < 0) {
14366 ma_assert(pDevice !=
NULL);
14368 pDevice->alsa.breakFromMainLoop =
MA_TRUE;
14374 ma_assert(pDevice !=
NULL);
14376 pDevice->alsa.breakFromMainLoop =
MA_FALSE;
14379 while (!pDevice->alsa.breakFromMainLoop && ma_device_read_from_client_and_write__alsa(pDevice)) {
14383 while (!pDevice->alsa.breakFromMainLoop && ma_device_read_and_send_to_client__alsa(pDevice)) {
14393 ma_snd_pcm_sframes_t resultALSA;
14395 ma_assert(pDevice !=
NULL);
14396 ma_assert(pFramesOut !=
NULL);
14398 if (pFramesRead !=
NULL) {
14403 resultALSA = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, pFramesOut, frameCount);
14404 if (resultALSA >= 0) {
14407 if (resultALSA == -EAGAIN) {
14410 }
else if (resultALSA == -EPIPE) {
14414 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, resultALSA,
MA_TRUE) < 0) {
14418 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
14422 resultALSA = ((ma_snd_pcm_readi_proc)pDevice->pContext->alsa.snd_pcm_readi)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture, pFramesOut, frameCount);
14423 if (resultALSA < 0) {
14430 if (pFramesRead !=
NULL) {
14431 *pFramesRead = resultALSA;
14439 ma_snd_pcm_sframes_t resultALSA;
14441 ma_assert(pDevice !=
NULL);
14442 ma_assert(pFrames !=
NULL);
14444 if (pFramesWritten !=
NULL) {
14445 *pFramesWritten = 0;
14449 resultALSA = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, pFrames, frameCount);
14450 if (resultALSA >= 0) {
14453 if (resultALSA == -EAGAIN) {
14456 }
else if (resultALSA == -EPIPE) {
14460 if (((ma_snd_pcm_recover_proc)pDevice->pContext->alsa.snd_pcm_recover)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, resultALSA,
MA_TRUE) < 0) {
14471 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) < 0) {
14475 resultALSA = ((ma_snd_pcm_writei_proc)pDevice->pContext->alsa.snd_pcm_writei)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback, pFrames, frameCount);
14476 if (resultALSA < 0) {
14483 if (pFramesWritten !=
NULL) {
14484 *pFramesWritten = resultALSA;
14495 ma_assert(pDevice !=
NULL);
14499 if (((ma_snd_pcm_start_proc)pDevice->pContext->alsa.snd_pcm_start)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
14504 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
14505 switch (pDevice->type)
14509 if (pDevice->alsa.isUsingMMapCapture || pDevice->alsa.isUsingMMapPlayback) {
14516 ma_uint8 capturedDeviceData[8192];
14517 ma_uint8 playbackDeviceData[8192];
14518 ma_uint32 capturedDeviceDataCapInFrames =
sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
14519 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
14522 ma_uint32 periodSizeInFrames = ma_min(pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods, pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods);
14524 while (totalFramesProcessed < periodSizeInFrames) {
14525 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
14527 ma_uint32 framesToProcess = framesRemaining;
14528 if (framesToProcess > capturedDeviceDataCapInFrames) {
14529 framesToProcess = capturedDeviceDataCapInFrames;
14532 result = ma_device_read__alsa(pDevice, capturedDeviceData, framesToProcess, &framesProcessed);
14538 pDevice->capture._dspFrameCount = framesToProcess;
14539 pDevice->capture._dspFrames = capturedDeviceData;
14544 ma_uint32 capturedDataCapInFrames =
sizeof(capturedData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
14545 ma_uint32 playbackDataCapInFrames =
sizeof(playbackData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
14547 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
14549 if (capturedFramesToProcess == 0) {
14553 ma_device__on_data(pDevice, playbackData, capturedData, capturedFramesToProcess);
14556 pDevice->playback._dspFrameCount = capturedFramesToProcess;
14557 pDevice->playback._dspFrames = playbackData;
14560 if (playbackDeviceFramesCount == 0) {
14564 result = ma_device_write__alsa(pDevice, playbackDeviceData, playbackDeviceFramesCount,
NULL);
14570 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
14575 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
14586 totalFramesProcessed += framesProcessed;
14593 if (pDevice->alsa.isUsingMMapCapture) {
14600 ma_uint8 intermediaryBuffer[8192];
14601 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
14602 ma_uint32 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
14604 while (framesReadThisPeriod < periodSizeInFrames) {
14605 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
14607 ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
14608 if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
14609 framesToReadThisIteration = intermediaryBufferSizeInFrames;
14612 result = ma_device_read__alsa(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
14618 ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
14620 framesReadThisPeriod += framesProcessed;
14627 if (pDevice->alsa.isUsingMMapPlayback) {
14634 ma_uint8 intermediaryBuffer[8192];
14635 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
14636 ma_uint32 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
14638 while (framesWrittenThisPeriod < periodSizeInFrames) {
14639 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
14641 ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
14642 if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
14643 framesToWriteThisIteration = intermediaryBufferSizeInFrames;
14646 ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
14648 result = ma_device_write__alsa(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
14654 framesWrittenThisPeriod += framesProcessed;
14667 ((ma_snd_pcm_drain_proc)pDevice->pContext->alsa.snd_pcm_drain)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture);
14670 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMCapture) < 0) {
14671 #ifdef MA_DEBUG_OUTPUT
14672 printf(
"[ALSA] Failed to prepare capture device after stopping.\n");
14678 ((ma_snd_pcm_drain_proc)pDevice->pContext->alsa.snd_pcm_drain)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback);
14681 if (((ma_snd_pcm_prepare_proc)pDevice->pContext->alsa.snd_pcm_prepare)((ma_snd_pcm_t*)pDevice->alsa.pPCMPlayback) < 0) {
14682 #ifdef MA_DEBUG_OUTPUT
14683 printf(
"[ALSA] Failed to prepare playback device after stopping.\n");
14693 ma_assert(pContext !=
NULL);
14697 ((ma_snd_config_update_free_global_proc)pContext->alsa.snd_config_update_free_global)();
14699 #ifndef MA_NO_RUNTIME_LINKING
14700 ma_dlclose(pContext, pContext->alsa.asoundSO);
14710 #ifndef MA_NO_RUNTIME_LINKING
14711 const char* libasoundNames[] = {
14717 for (i = 0; i < ma_countof(libasoundNames); ++i) {
14718 pContext->alsa.asoundSO = ma_dlopen(pContext, libasoundNames[i]);
14719 if (pContext->alsa.asoundSO !=
NULL) {
14724 if (pContext->alsa.asoundSO ==
NULL) {
14725 #ifdef MA_DEBUG_OUTPUT
14726 printf(
"[ALSA] Failed to open shared object.\n");
14731 pContext->alsa.snd_pcm_open = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_open");
14732 pContext->alsa.snd_pcm_close = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_close");
14733 pContext->alsa.snd_pcm_hw_params_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_sizeof");
14734 pContext->alsa.snd_pcm_hw_params_any = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_any");
14735 pContext->alsa.snd_pcm_hw_params_set_format = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_format");
14736 pContext->alsa.snd_pcm_hw_params_set_format_first = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_format_first");
14737 pContext->alsa.snd_pcm_hw_params_get_format_mask = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_format_mask");
14738 pContext->alsa.snd_pcm_hw_params_set_channels_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_channels_near");
14739 pContext->alsa.snd_pcm_hw_params_set_rate_resample = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_rate_resample");
14740 pContext->alsa.snd_pcm_hw_params_set_rate_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_rate_near");
14741 pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_buffer_size_near");
14742 pContext->alsa.snd_pcm_hw_params_set_periods_near = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_periods_near");
14743 pContext->alsa.snd_pcm_hw_params_set_access = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_set_access");
14744 pContext->alsa.snd_pcm_hw_params_get_format = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_format");
14745 pContext->alsa.snd_pcm_hw_params_get_channels = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_channels");
14746 pContext->alsa.snd_pcm_hw_params_get_channels_min = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_channels_min");
14747 pContext->alsa.snd_pcm_hw_params_get_channels_max = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_channels_max");
14748 pContext->alsa.snd_pcm_hw_params_get_rate = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_rate");
14749 pContext->alsa.snd_pcm_hw_params_get_rate_min = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_rate_min");
14750 pContext->alsa.snd_pcm_hw_params_get_rate_max = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_rate_max");
14751 pContext->alsa.snd_pcm_hw_params_get_buffer_size = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_buffer_size");
14752 pContext->alsa.snd_pcm_hw_params_get_periods = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_periods");
14753 pContext->alsa.snd_pcm_hw_params_get_access = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params_get_access");
14754 pContext->alsa.snd_pcm_hw_params = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_hw_params");
14755 pContext->alsa.snd_pcm_sw_params_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_sizeof");
14756 pContext->alsa.snd_pcm_sw_params_current = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_current");
14757 pContext->alsa.snd_pcm_sw_params_get_boundary = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_get_boundary");
14758 pContext->alsa.snd_pcm_sw_params_set_avail_min = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_set_avail_min");
14759 pContext->alsa.snd_pcm_sw_params_set_start_threshold = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_set_start_threshold");
14760 pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params_set_stop_threshold");
14761 pContext->alsa.snd_pcm_sw_params = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_sw_params");
14762 pContext->alsa.snd_pcm_format_mask_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_format_mask_sizeof");
14763 pContext->alsa.snd_pcm_format_mask_test = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_format_mask_test");
14764 pContext->alsa.snd_pcm_get_chmap = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_get_chmap");
14765 pContext->alsa.snd_pcm_state = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_state");
14766 pContext->alsa.snd_pcm_prepare = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_prepare");
14767 pContext->alsa.snd_pcm_start = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_start");
14768 pContext->alsa.snd_pcm_drop = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_drop");
14769 pContext->alsa.snd_pcm_drain = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_drain");
14770 pContext->alsa.snd_device_name_hint = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_device_name_hint");
14771 pContext->alsa.snd_device_name_get_hint = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_device_name_get_hint");
14772 pContext->alsa.snd_card_get_index = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_card_get_index");
14773 pContext->alsa.snd_device_name_free_hint = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_device_name_free_hint");
14774 pContext->alsa.snd_pcm_mmap_begin = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_mmap_begin");
14775 pContext->alsa.snd_pcm_mmap_commit = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_mmap_commit");
14776 pContext->alsa.snd_pcm_recover = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_recover");
14777 pContext->alsa.snd_pcm_readi = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_readi");
14778 pContext->alsa.snd_pcm_writei = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_writei");
14779 pContext->alsa.snd_pcm_avail = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_avail");
14780 pContext->alsa.snd_pcm_avail_update = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_avail_update");
14781 pContext->alsa.snd_pcm_wait = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_wait");
14782 pContext->alsa.snd_pcm_info = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_info");
14783 pContext->alsa.snd_pcm_info_sizeof = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_info_sizeof");
14784 pContext->alsa.snd_pcm_info_get_name = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_pcm_info_get_name");
14785 pContext->alsa.snd_config_update_free_global = (
ma_proc)ma_dlsym(pContext, pContext->alsa.asoundSO,
"snd_config_update_free_global");
14788 ma_snd_pcm_open_proc _snd_pcm_open = snd_pcm_open;
14789 ma_snd_pcm_close_proc _snd_pcm_close = snd_pcm_close;
14790 ma_snd_pcm_hw_params_sizeof_proc _snd_pcm_hw_params_sizeof = snd_pcm_hw_params_sizeof;
14791 ma_snd_pcm_hw_params_any_proc _snd_pcm_hw_params_any = snd_pcm_hw_params_any;
14792 ma_snd_pcm_hw_params_set_format_proc _snd_pcm_hw_params_set_format = snd_pcm_hw_params_set_format;
14793 ma_snd_pcm_hw_params_set_format_first_proc _snd_pcm_hw_params_set_format_first = snd_pcm_hw_params_set_format_first;
14794 ma_snd_pcm_hw_params_get_format_mask_proc _snd_pcm_hw_params_get_format_mask = snd_pcm_hw_params_get_format_mask;
14795 ma_snd_pcm_hw_params_set_channels_near_proc _snd_pcm_hw_params_set_channels_near = snd_pcm_hw_params_set_channels_near;
14796 ma_snd_pcm_hw_params_set_rate_resample_proc _snd_pcm_hw_params_set_rate_resample = snd_pcm_hw_params_set_rate_resample;
14797 ma_snd_pcm_hw_params_set_rate_near_proc _snd_pcm_hw_params_set_rate_near = snd_pcm_hw_params_set_rate_near;
14798 ma_snd_pcm_hw_params_set_buffer_size_near_proc _snd_pcm_hw_params_set_buffer_size_near = snd_pcm_hw_params_set_buffer_size_near;
14799 ma_snd_pcm_hw_params_set_periods_near_proc _snd_pcm_hw_params_set_periods_near = snd_pcm_hw_params_set_periods_near;
14800 ma_snd_pcm_hw_params_set_access_proc _snd_pcm_hw_params_set_access = snd_pcm_hw_params_set_access;
14801 ma_snd_pcm_hw_params_get_format_proc _snd_pcm_hw_params_get_format = snd_pcm_hw_params_get_format;
14802 ma_snd_pcm_hw_params_get_channels_proc _snd_pcm_hw_params_get_channels = snd_pcm_hw_params_get_channels;
14803 ma_snd_pcm_hw_params_get_channels_min_proc _snd_pcm_hw_params_get_channels_min = snd_pcm_hw_params_get_channels_min;
14804 ma_snd_pcm_hw_params_get_channels_max_proc _snd_pcm_hw_params_get_channels_max = snd_pcm_hw_params_get_channels_max;
14805 ma_snd_pcm_hw_params_get_rate_proc _snd_pcm_hw_params_get_rate = snd_pcm_hw_params_get_rate;
14806 ma_snd_pcm_hw_params_get_rate_min_proc _snd_pcm_hw_params_get_rate_min = snd_pcm_hw_params_get_rate_min;
14807 ma_snd_pcm_hw_params_get_rate_max_proc _snd_pcm_hw_params_get_rate_max = snd_pcm_hw_params_get_rate_max;
14808 ma_snd_pcm_hw_params_get_buffer_size_proc _snd_pcm_hw_params_get_buffer_size = snd_pcm_hw_params_get_buffer_size;
14809 ma_snd_pcm_hw_params_get_periods_proc _snd_pcm_hw_params_get_periods = snd_pcm_hw_params_get_periods;
14810 ma_snd_pcm_hw_params_get_access_proc _snd_pcm_hw_params_get_access = snd_pcm_hw_params_get_access;
14811 ma_snd_pcm_hw_params_proc _snd_pcm_hw_params = snd_pcm_hw_params;
14812 ma_snd_pcm_sw_params_sizeof_proc _snd_pcm_sw_params_sizeof = snd_pcm_sw_params_sizeof;
14813 ma_snd_pcm_sw_params_current_proc _snd_pcm_sw_params_current = snd_pcm_sw_params_current;
14814 ma_snd_pcm_sw_params_get_boundary_proc _snd_pcm_sw_params_get_boundary = snd_pcm_sw_params_get_boundary;
14815 ma_snd_pcm_sw_params_set_avail_min_proc _snd_pcm_sw_params_set_avail_min = snd_pcm_sw_params_set_avail_min;
14816 ma_snd_pcm_sw_params_set_start_threshold_proc _snd_pcm_sw_params_set_start_threshold = snd_pcm_sw_params_set_start_threshold;
14817 ma_snd_pcm_sw_params_set_stop_threshold_proc _snd_pcm_sw_params_set_stop_threshold = snd_pcm_sw_params_set_stop_threshold;
14818 ma_snd_pcm_sw_params_proc _snd_pcm_sw_params = snd_pcm_sw_params;
14819 ma_snd_pcm_format_mask_sizeof_proc _snd_pcm_format_mask_sizeof = snd_pcm_format_mask_sizeof;
14820 ma_snd_pcm_format_mask_test_proc _snd_pcm_format_mask_test = snd_pcm_format_mask_test;
14821 ma_snd_pcm_get_chmap_proc _snd_pcm_get_chmap = snd_pcm_get_chmap;
14822 ma_snd_pcm_state_proc _snd_pcm_state = snd_pcm_state;
14823 ma_snd_pcm_prepare_proc _snd_pcm_prepare = snd_pcm_prepare;
14824 ma_snd_pcm_start_proc _snd_pcm_start = snd_pcm_start;
14825 ma_snd_pcm_drop_proc _snd_pcm_drop = snd_pcm_drop;
14826 ma_snd_pcm_drain_proc _snd_pcm_drain = snd_pcm_drain;
14827 ma_snd_device_name_hint_proc _snd_device_name_hint = snd_device_name_hint;
14828 ma_snd_device_name_get_hint_proc _snd_device_name_get_hint = snd_device_name_get_hint;
14829 ma_snd_card_get_index_proc _snd_card_get_index = snd_card_get_index;
14830 ma_snd_device_name_free_hint_proc _snd_device_name_free_hint = snd_device_name_free_hint;
14831 ma_snd_pcm_mmap_begin_proc _snd_pcm_mmap_begin = snd_pcm_mmap_begin;
14832 ma_snd_pcm_mmap_commit_proc _snd_pcm_mmap_commit = snd_pcm_mmap_commit;
14833 ma_snd_pcm_recover_proc _snd_pcm_recover = snd_pcm_recover;
14834 ma_snd_pcm_readi_proc _snd_pcm_readi = snd_pcm_readi;
14835 ma_snd_pcm_writei_proc _snd_pcm_writei = snd_pcm_writei;
14836 ma_snd_pcm_avail_proc _snd_pcm_avail = snd_pcm_avail;
14837 ma_snd_pcm_avail_update_proc _snd_pcm_avail_update = snd_pcm_avail_update;
14838 ma_snd_pcm_wait_proc _snd_pcm_wait = snd_pcm_wait;
14839 ma_snd_pcm_info_proc _snd_pcm_info = snd_pcm_info;
14840 ma_snd_pcm_info_sizeof_proc _snd_pcm_info_sizeof = snd_pcm_info_sizeof;
14841 ma_snd_pcm_info_get_name_proc _snd_pcm_info_get_name = snd_pcm_info_get_name;
14842 ma_snd_config_update_free_global_proc _snd_config_update_free_global = snd_config_update_free_global;
14844 pContext->alsa.snd_pcm_open = (
ma_proc)_snd_pcm_open;
14845 pContext->alsa.snd_pcm_close = (
ma_proc)_snd_pcm_close;
14846 pContext->alsa.snd_pcm_hw_params_sizeof = (
ma_proc)_snd_pcm_hw_params_sizeof;
14847 pContext->alsa.snd_pcm_hw_params_any = (
ma_proc)_snd_pcm_hw_params_any;
14848 pContext->alsa.snd_pcm_hw_params_set_format = (
ma_proc)_snd_pcm_hw_params_set_format;
14849 pContext->alsa.snd_pcm_hw_params_set_format_first = (
ma_proc)_snd_pcm_hw_params_set_format_first;
14850 pContext->alsa.snd_pcm_hw_params_get_format_mask = (
ma_proc)_snd_pcm_hw_params_get_format_mask;
14851 pContext->alsa.snd_pcm_hw_params_set_channels_near = (
ma_proc)_snd_pcm_hw_params_set_channels_near;
14852 pContext->alsa.snd_pcm_hw_params_set_rate_resample = (
ma_proc)_snd_pcm_hw_params_set_rate_resample;
14853 pContext->alsa.snd_pcm_hw_params_set_rate_near = (
ma_proc)_snd_pcm_hw_params_set_rate_near;
14854 pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (
ma_proc)_snd_pcm_hw_params_set_buffer_size_near;
14855 pContext->alsa.snd_pcm_hw_params_set_periods_near = (
ma_proc)_snd_pcm_hw_params_set_periods_near;
14856 pContext->alsa.snd_pcm_hw_params_set_access = (
ma_proc)_snd_pcm_hw_params_set_access;
14857 pContext->alsa.snd_pcm_hw_params_get_format = (
ma_proc)_snd_pcm_hw_params_get_format;
14858 pContext->alsa.snd_pcm_hw_params_get_channels = (
ma_proc)_snd_pcm_hw_params_get_channels;
14859 pContext->alsa.snd_pcm_hw_params_get_channels_min = (
ma_proc)_snd_pcm_hw_params_get_channels_min;
14860 pContext->alsa.snd_pcm_hw_params_get_channels_max = (
ma_proc)_snd_pcm_hw_params_get_channels_max;
14861 pContext->alsa.snd_pcm_hw_params_get_rate = (
ma_proc)_snd_pcm_hw_params_get_rate;
14862 pContext->alsa.snd_pcm_hw_params_get_buffer_size = (
ma_proc)_snd_pcm_hw_params_get_buffer_size;
14863 pContext->alsa.snd_pcm_hw_params_get_periods = (
ma_proc)_snd_pcm_hw_params_get_periods;
14864 pContext->alsa.snd_pcm_hw_params_get_access = (
ma_proc)_snd_pcm_hw_params_get_access;
14865 pContext->alsa.snd_pcm_hw_params = (
ma_proc)_snd_pcm_hw_params;
14866 pContext->alsa.snd_pcm_sw_params_sizeof = (
ma_proc)_snd_pcm_sw_params_sizeof;
14867 pContext->alsa.snd_pcm_sw_params_current = (
ma_proc)_snd_pcm_sw_params_current;
14868 pContext->alsa.snd_pcm_sw_params_get_boundary = (
ma_proc)_snd_pcm_sw_params_get_boundary;
14869 pContext->alsa.snd_pcm_sw_params_set_avail_min = (
ma_proc)_snd_pcm_sw_params_set_avail_min;
14870 pContext->alsa.snd_pcm_sw_params_set_start_threshold = (
ma_proc)_snd_pcm_sw_params_set_start_threshold;
14871 pContext->alsa.snd_pcm_sw_params_set_stop_threshold = (
ma_proc)_snd_pcm_sw_params_set_stop_threshold;
14872 pContext->alsa.snd_pcm_sw_params = (
ma_proc)_snd_pcm_sw_params;
14873 pContext->alsa.snd_pcm_format_mask_sizeof = (
ma_proc)_snd_pcm_format_mask_sizeof;
14874 pContext->alsa.snd_pcm_format_mask_test = (
ma_proc)_snd_pcm_format_mask_test;
14875 pContext->alsa.snd_pcm_get_chmap = (
ma_proc)_snd_pcm_get_chmap;
14876 pContext->alsa.snd_pcm_state = (
ma_proc)_snd_pcm_state;
14877 pContext->alsa.snd_pcm_prepare = (
ma_proc)_snd_pcm_prepare;
14878 pContext->alsa.snd_pcm_start = (
ma_proc)_snd_pcm_start;
14879 pContext->alsa.snd_pcm_drop = (
ma_proc)_snd_pcm_drop;
14880 pContext->alsa.snd_pcm_drain = (
ma_proc)_snd_pcm_drain;
14881 pContext->alsa.snd_device_name_hint = (
ma_proc)_snd_device_name_hint;
14882 pContext->alsa.snd_device_name_get_hint = (
ma_proc)_snd_device_name_get_hint;
14883 pContext->alsa.snd_card_get_index = (
ma_proc)_snd_card_get_index;
14884 pContext->alsa.snd_device_name_free_hint = (
ma_proc)_snd_device_name_free_hint;
14885 pContext->alsa.snd_pcm_mmap_begin = (
ma_proc)_snd_pcm_mmap_begin;
14886 pContext->alsa.snd_pcm_mmap_commit = (
ma_proc)_snd_pcm_mmap_commit;
14887 pContext->alsa.snd_pcm_recover = (
ma_proc)_snd_pcm_recover;
14888 pContext->alsa.snd_pcm_readi = (
ma_proc)_snd_pcm_readi;
14889 pContext->alsa.snd_pcm_writei = (
ma_proc)_snd_pcm_writei;
14890 pContext->alsa.snd_pcm_avail = (
ma_proc)_snd_pcm_avail;
14891 pContext->alsa.snd_pcm_avail_update = (
ma_proc)_snd_pcm_avail_update;
14892 pContext->alsa.snd_pcm_wait = (
ma_proc)_snd_pcm_wait;
14893 pContext->alsa.snd_pcm_info = (
ma_proc)_snd_pcm_info;
14894 pContext->alsa.snd_pcm_info_sizeof = (
ma_proc)_snd_pcm_info_sizeof;
14895 pContext->alsa.snd_pcm_info_get_name = (
ma_proc)_snd_pcm_info_get_name;
14896 pContext->alsa.snd_config_update_free_global = (
ma_proc)_snd_config_update_free_global;
14902 ma_context_post_error(pContext,
NULL,
MA_LOG_LEVEL_ERROR,
"[ALSA] WARNING: Failed to initialize mutex for internal device enumeration.",
MA_ERROR);
14905 pContext->
onUninit = ma_context_uninit__alsa;
14907 pContext->
onEnumDevices = ma_context_enumerate_devices__alsa;
14926 #ifdef MA_HAS_PULSEAUDIO
14934 #ifdef MA_NO_RUNTIME_LINKING
14935 #include <pulse/pulseaudio.h>
14937 #define MA_PA_OK PA_OK
14938 #define MA_PA_ERR_ACCESS PA_ERR_ACCESS
14939 #define MA_PA_ERR_INVALID PA_ERR_INVALID
14940 #define MA_PA_ERR_NOENTITY PA_ERR_NOENTITY
14942 #define MA_PA_CHANNELS_MAX PA_CHANNELS_MAX
14943 #define MA_PA_RATE_MAX PA_RATE_MAX
14945 typedef pa_context_flags_t ma_pa_context_flags_t;
14946 #define MA_PA_CONTEXT_NOFLAGS PA_CONTEXT_NOFLAGS
14947 #define MA_PA_CONTEXT_NOAUTOSPAWN PA_CONTEXT_NOAUTOSPAWN
14948 #define MA_PA_CONTEXT_NOFAIL PA_CONTEXT_NOFAIL
14950 typedef pa_stream_flags_t ma_pa_stream_flags_t;
14951 #define MA_PA_STREAM_NOFLAGS PA_STREAM_NOFLAGS
14952 #define MA_PA_STREAM_START_CORKED PA_STREAM_START_CORKED
14953 #define MA_PA_STREAM_INTERPOLATE_TIMING PA_STREAM_INTERPOLATE_TIMING
14954 #define MA_PA_STREAM_NOT_MONOTONIC PA_STREAM_NOT_MONOTONIC
14955 #define MA_PA_STREAM_AUTO_TIMING_UPDATE PA_STREAM_AUTO_TIMING_UPDATE
14956 #define MA_PA_STREAM_NO_REMAP_CHANNELS PA_STREAM_NO_REMAP_CHANNELS
14957 #define MA_PA_STREAM_NO_REMIX_CHANNELS PA_STREAM_NO_REMIX_CHANNELS
14958 #define MA_PA_STREAM_FIX_FORMAT PA_STREAM_FIX_FORMAT
14959 #define MA_PA_STREAM_FIX_RATE PA_STREAM_FIX_RATE
14960 #define MA_PA_STREAM_FIX_CHANNELS PA_STREAM_FIX_CHANNELS
14961 #define MA_PA_STREAM_DONT_MOVE PA_STREAM_DONT_MOVE
14962 #define MA_PA_STREAM_VARIABLE_RATE PA_STREAM_VARIABLE_RATE
14963 #define MA_PA_STREAM_PEAK_DETECT PA_STREAM_PEAK_DETECT
14964 #define MA_PA_STREAM_START_MUTED PA_STREAM_START_MUTED
14965 #define MA_PA_STREAM_ADJUST_LATENCY PA_STREAM_ADJUST_LATENCY
14966 #define MA_PA_STREAM_EARLY_REQUESTS PA_STREAM_EARLY_REQUESTS
14967 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
14968 #define MA_PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED
14969 #define MA_PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
14970 #define MA_PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
14971 #define MA_PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH
14973 typedef pa_sink_flags_t ma_pa_sink_flags_t;
14974 #define MA_PA_SINK_NOFLAGS PA_SINK_NOFLAGS
14975 #define MA_PA_SINK_HW_VOLUME_CTRL PA_SINK_HW_VOLUME_CTRL
14976 #define MA_PA_SINK_LATENCY PA_SINK_LATENCY
14977 #define MA_PA_SINK_HARDWARE PA_SINK_HARDWARE
14978 #define MA_PA_SINK_NETWORK PA_SINK_NETWORK
14979 #define MA_PA_SINK_HW_MUTE_CTRL PA_SINK_HW_MUTE_CTRL
14980 #define MA_PA_SINK_DECIBEL_VOLUME PA_SINK_DECIBEL_VOLUME
14981 #define MA_PA_SINK_FLAT_VOLUME PA_SINK_FLAT_VOLUME
14982 #define MA_PA_SINK_DYNAMIC_LATENCY PA_SINK_DYNAMIC_LATENCY
14983 #define MA_PA_SINK_SET_FORMATS PA_SINK_SET_FORMATS
14985 typedef pa_source_flags_t ma_pa_source_flags_t;
14986 #define MA_PA_SOURCE_NOFLAGS PA_SOURCE_NOFLAGS
14987 #define MA_PA_SOURCE_HW_VOLUME_CTRL PA_SOURCE_HW_VOLUME_CTRL
14988 #define MA_PA_SOURCE_LATENCY PA_SOURCE_LATENCY
14989 #define MA_PA_SOURCE_HARDWARE PA_SOURCE_HARDWARE
14990 #define MA_PA_SOURCE_NETWORK PA_SOURCE_NETWORK
14991 #define MA_PA_SOURCE_HW_MUTE_CTRL PA_SOURCE_HW_MUTE_CTRL
14992 #define MA_PA_SOURCE_DECIBEL_VOLUME PA_SOURCE_DECIBEL_VOLUME
14993 #define MA_PA_SOURCE_DYNAMIC_LATENCY PA_SOURCE_DYNAMIC_LATENCY
14994 #define MA_PA_SOURCE_FLAT_VOLUME PA_SOURCE_FLAT_VOLUME
14996 typedef pa_context_state_t ma_pa_context_state_t;
14997 #define MA_PA_CONTEXT_UNCONNECTED PA_CONTEXT_UNCONNECTED
14998 #define MA_PA_CONTEXT_CONNECTING PA_CONTEXT_CONNECTING
14999 #define MA_PA_CONTEXT_AUTHORIZING PA_CONTEXT_AUTHORIZING
15000 #define MA_PA_CONTEXT_SETTING_NAME PA_CONTEXT_SETTING_NAME
15001 #define MA_PA_CONTEXT_READY PA_CONTEXT_READY
15002 #define MA_PA_CONTEXT_FAILED PA_CONTEXT_FAILED
15003 #define MA_PA_CONTEXT_TERMINATED PA_CONTEXT_TERMINATED
15005 typedef pa_stream_state_t ma_pa_stream_state_t;
15006 #define MA_PA_STREAM_UNCONNECTED PA_STREAM_UNCONNECTED
15007 #define MA_PA_STREAM_CREATING PA_STREAM_CREATING
15008 #define MA_PA_STREAM_READY PA_STREAM_READY
15009 #define MA_PA_STREAM_FAILED PA_STREAM_FAILED
15010 #define MA_PA_STREAM_TERMINATED PA_STREAM_TERMINATED
15012 typedef pa_operation_state_t ma_pa_operation_state_t;
15013 #define MA_PA_OPERATION_RUNNING PA_OPERATION_RUNNING
15014 #define MA_PA_OPERATION_DONE PA_OPERATION_DONE
15015 #define MA_PA_OPERATION_CANCELLED PA_OPERATION_CANCELLED
15017 typedef pa_sink_state_t ma_pa_sink_state_t;
15018 #define MA_PA_SINK_INVALID_STATE PA_SINK_INVALID_STATE
15019 #define MA_PA_SINK_RUNNING PA_SINK_RUNNING
15020 #define MA_PA_SINK_IDLE PA_SINK_IDLE
15021 #define MA_PA_SINK_SUSPENDED PA_SINK_SUSPENDED
15023 typedef pa_source_state_t ma_pa_source_state_t;
15024 #define MA_PA_SOURCE_INVALID_STATE PA_SOURCE_INVALID_STATE
15025 #define MA_PA_SOURCE_RUNNING PA_SOURCE_RUNNING
15026 #define MA_PA_SOURCE_IDLE PA_SOURCE_IDLE
15027 #define MA_PA_SOURCE_SUSPENDED PA_SOURCE_SUSPENDED
15029 typedef pa_seek_mode_t ma_pa_seek_mode_t;
15030 #define MA_PA_SEEK_RELATIVE PA_SEEK_RELATIVE
15031 #define MA_PA_SEEK_ABSOLUTE PA_SEEK_ABSOLUTE
15032 #define MA_PA_SEEK_RELATIVE_ON_READ PA_SEEK_RELATIVE_ON_READ
15033 #define MA_PA_SEEK_RELATIVE_END PA_SEEK_RELATIVE_END
15035 typedef pa_channel_position_t ma_pa_channel_position_t;
15036 #define MA_PA_CHANNEL_POSITION_INVALID PA_CHANNEL_POSITION_INVALID
15037 #define MA_PA_CHANNEL_POSITION_MONO PA_CHANNEL_POSITION_MONO
15038 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT PA_CHANNEL_POSITION_FRONT_LEFT
15039 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT PA_CHANNEL_POSITION_FRONT_RIGHT
15040 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER PA_CHANNEL_POSITION_FRONT_CENTER
15041 #define MA_PA_CHANNEL_POSITION_REAR_CENTER PA_CHANNEL_POSITION_REAR_CENTER
15042 #define MA_PA_CHANNEL_POSITION_REAR_LEFT PA_CHANNEL_POSITION_REAR_LEFT
15043 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT PA_CHANNEL_POSITION_REAR_RIGHT
15044 #define MA_PA_CHANNEL_POSITION_LFE PA_CHANNEL_POSITION_LFE
15045 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
15046 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
15047 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT PA_CHANNEL_POSITION_SIDE_LEFT
15048 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT PA_CHANNEL_POSITION_SIDE_RIGHT
15049 #define MA_PA_CHANNEL_POSITION_AUX0 PA_CHANNEL_POSITION_AUX0
15050 #define MA_PA_CHANNEL_POSITION_AUX1 PA_CHANNEL_POSITION_AUX1
15051 #define MA_PA_CHANNEL_POSITION_AUX2 PA_CHANNEL_POSITION_AUX2
15052 #define MA_PA_CHANNEL_POSITION_AUX3 PA_CHANNEL_POSITION_AUX3
15053 #define MA_PA_CHANNEL_POSITION_AUX4 PA_CHANNEL_POSITION_AUX4
15054 #define MA_PA_CHANNEL_POSITION_AUX5 PA_CHANNEL_POSITION_AUX5
15055 #define MA_PA_CHANNEL_POSITION_AUX6 PA_CHANNEL_POSITION_AUX6
15056 #define MA_PA_CHANNEL_POSITION_AUX7 PA_CHANNEL_POSITION_AUX7
15057 #define MA_PA_CHANNEL_POSITION_AUX8 PA_CHANNEL_POSITION_AUX8
15058 #define MA_PA_CHANNEL_POSITION_AUX9 PA_CHANNEL_POSITION_AUX9
15059 #define MA_PA_CHANNEL_POSITION_AUX10 PA_CHANNEL_POSITION_AUX10
15060 #define MA_PA_CHANNEL_POSITION_AUX11 PA_CHANNEL_POSITION_AUX11
15061 #define MA_PA_CHANNEL_POSITION_AUX12 PA_CHANNEL_POSITION_AUX12
15062 #define MA_PA_CHANNEL_POSITION_AUX13 PA_CHANNEL_POSITION_AUX13
15063 #define MA_PA_CHANNEL_POSITION_AUX14 PA_CHANNEL_POSITION_AUX14
15064 #define MA_PA_CHANNEL_POSITION_AUX15 PA_CHANNEL_POSITION_AUX15
15065 #define MA_PA_CHANNEL_POSITION_AUX16 PA_CHANNEL_POSITION_AUX16
15066 #define MA_PA_CHANNEL_POSITION_AUX17 PA_CHANNEL_POSITION_AUX17
15067 #define MA_PA_CHANNEL_POSITION_AUX18 PA_CHANNEL_POSITION_AUX18
15068 #define MA_PA_CHANNEL_POSITION_AUX19 PA_CHANNEL_POSITION_AUX19
15069 #define MA_PA_CHANNEL_POSITION_AUX20 PA_CHANNEL_POSITION_AUX20
15070 #define MA_PA_CHANNEL_POSITION_AUX21 PA_CHANNEL_POSITION_AUX21
15071 #define MA_PA_CHANNEL_POSITION_AUX22 PA_CHANNEL_POSITION_AUX22
15072 #define MA_PA_CHANNEL_POSITION_AUX23 PA_CHANNEL_POSITION_AUX23
15073 #define MA_PA_CHANNEL_POSITION_AUX24 PA_CHANNEL_POSITION_AUX24
15074 #define MA_PA_CHANNEL_POSITION_AUX25 PA_CHANNEL_POSITION_AUX25
15075 #define MA_PA_CHANNEL_POSITION_AUX26 PA_CHANNEL_POSITION_AUX26
15076 #define MA_PA_CHANNEL_POSITION_AUX27 PA_CHANNEL_POSITION_AUX27
15077 #define MA_PA_CHANNEL_POSITION_AUX28 PA_CHANNEL_POSITION_AUX28
15078 #define MA_PA_CHANNEL_POSITION_AUX29 PA_CHANNEL_POSITION_AUX29
15079 #define MA_PA_CHANNEL_POSITION_AUX30 PA_CHANNEL_POSITION_AUX30
15080 #define MA_PA_CHANNEL_POSITION_AUX31 PA_CHANNEL_POSITION_AUX31
15081 #define MA_PA_CHANNEL_POSITION_TOP_CENTER PA_CHANNEL_POSITION_TOP_CENTER
15082 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT PA_CHANNEL_POSITION_TOP_FRONT_LEFT
15083 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
15084 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER PA_CHANNEL_POSITION_TOP_FRONT_CENTER
15085 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT PA_CHANNEL_POSITION_TOP_REAR_LEFT
15086 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT PA_CHANNEL_POSITION_TOP_REAR_RIGHT
15087 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER PA_CHANNEL_POSITION_TOP_REAR_CENTER
15088 #define MA_PA_CHANNEL_POSITION_LEFT PA_CHANNEL_POSITION_LEFT
15089 #define MA_PA_CHANNEL_POSITION_RIGHT PA_CHANNEL_POSITION_RIGHT
15090 #define MA_PA_CHANNEL_POSITION_CENTER PA_CHANNEL_POSITION_CENTER
15091 #define MA_PA_CHANNEL_POSITION_SUBWOOFER PA_CHANNEL_POSITION_SUBWOOFER
15093 typedef pa_channel_map_def_t ma_pa_channel_map_def_t;
15094 #define MA_PA_CHANNEL_MAP_AIFF PA_CHANNEL_MAP_AIFF
15095 #define MA_PA_CHANNEL_MAP_ALSA PA_CHANNEL_MAP_ALSA
15096 #define MA_PA_CHANNEL_MAP_AUX PA_CHANNEL_MAP_AUX
15097 #define MA_PA_CHANNEL_MAP_WAVEEX PA_CHANNEL_MAP_WAVEEX
15098 #define MA_PA_CHANNEL_MAP_OSS PA_CHANNEL_MAP_OSS
15099 #define MA_PA_CHANNEL_MAP_DEFAULT PA_CHANNEL_MAP_DEFAULT
15101 typedef pa_sample_format_t ma_pa_sample_format_t;
15102 #define MA_PA_SAMPLE_INVALID PA_SAMPLE_INVALID
15103 #define MA_PA_SAMPLE_U8 PA_SAMPLE_U8
15104 #define MA_PA_SAMPLE_ALAW PA_SAMPLE_ALAW
15105 #define MA_PA_SAMPLE_ULAW PA_SAMPLE_ULAW
15106 #define MA_PA_SAMPLE_S16LE PA_SAMPLE_S16LE
15107 #define MA_PA_SAMPLE_S16BE PA_SAMPLE_S16BE
15108 #define MA_PA_SAMPLE_FLOAT32LE PA_SAMPLE_FLOAT32LE
15109 #define MA_PA_SAMPLE_FLOAT32BE PA_SAMPLE_FLOAT32BE
15110 #define MA_PA_SAMPLE_S32LE PA_SAMPLE_S32LE
15111 #define MA_PA_SAMPLE_S32BE PA_SAMPLE_S32BE
15112 #define MA_PA_SAMPLE_S24LE PA_SAMPLE_S24LE
15113 #define MA_PA_SAMPLE_S24BE PA_SAMPLE_S24BE
15114 #define MA_PA_SAMPLE_S24_32LE PA_SAMPLE_S24_32LE
15115 #define MA_PA_SAMPLE_S24_32BE PA_SAMPLE_S24_32BE
15117 typedef pa_mainloop ma_pa_mainloop;
15118 typedef pa_mainloop_api ma_pa_mainloop_api;
15119 typedef pa_context ma_pa_context;
15120 typedef pa_operation ma_pa_operation;
15121 typedef pa_stream ma_pa_stream;
15122 typedef pa_spawn_api ma_pa_spawn_api;
15123 typedef pa_buffer_attr ma_pa_buffer_attr;
15124 typedef pa_channel_map ma_pa_channel_map;
15125 typedef pa_cvolume ma_pa_cvolume;
15126 typedef pa_sample_spec ma_pa_sample_spec;
15127 typedef pa_sink_info ma_pa_sink_info;
15128 typedef pa_source_info ma_pa_source_info;
15130 typedef pa_context_notify_cb_t ma_pa_context_notify_cb_t;
15131 typedef pa_sink_info_cb_t ma_pa_sink_info_cb_t;
15132 typedef pa_source_info_cb_t ma_pa_source_info_cb_t;
15133 typedef pa_stream_success_cb_t ma_pa_stream_success_cb_t;
15134 typedef pa_stream_request_cb_t ma_pa_stream_request_cb_t;
15135 typedef pa_free_cb_t ma_pa_free_cb_t;
15138 #define MA_PA_ERR_ACCESS 1
15139 #define MA_PA_ERR_INVALID 2
15140 #define MA_PA_ERR_NOENTITY 5
15142 #define MA_PA_CHANNELS_MAX 32
15143 #define MA_PA_RATE_MAX 384000
15145 typedef int ma_pa_context_flags_t;
15146 #define MA_PA_CONTEXT_NOFLAGS 0x00000000
15147 #define MA_PA_CONTEXT_NOAUTOSPAWN 0x00000001
15148 #define MA_PA_CONTEXT_NOFAIL 0x00000002
15150 typedef int ma_pa_stream_flags_t;
15151 #define MA_PA_STREAM_NOFLAGS 0x00000000
15152 #define MA_PA_STREAM_START_CORKED 0x00000001
15153 #define MA_PA_STREAM_INTERPOLATE_TIMING 0x00000002
15154 #define MA_PA_STREAM_NOT_MONOTONIC 0x00000004
15155 #define MA_PA_STREAM_AUTO_TIMING_UPDATE 0x00000008
15156 #define MA_PA_STREAM_NO_REMAP_CHANNELS 0x00000010
15157 #define MA_PA_STREAM_NO_REMIX_CHANNELS 0x00000020
15158 #define MA_PA_STREAM_FIX_FORMAT 0x00000040
15159 #define MA_PA_STREAM_FIX_RATE 0x00000080
15160 #define MA_PA_STREAM_FIX_CHANNELS 0x00000100
15161 #define MA_PA_STREAM_DONT_MOVE 0x00000200
15162 #define MA_PA_STREAM_VARIABLE_RATE 0x00000400
15163 #define MA_PA_STREAM_PEAK_DETECT 0x00000800
15164 #define MA_PA_STREAM_START_MUTED 0x00001000
15165 #define MA_PA_STREAM_ADJUST_LATENCY 0x00002000
15166 #define MA_PA_STREAM_EARLY_REQUESTS 0x00004000
15167 #define MA_PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND 0x00008000
15168 #define MA_PA_STREAM_START_UNMUTED 0x00010000
15169 #define MA_PA_STREAM_FAIL_ON_SUSPEND 0x00020000
15170 #define MA_PA_STREAM_RELATIVE_VOLUME 0x00040000
15171 #define MA_PA_STREAM_PASSTHROUGH 0x00080000
15173 typedef int ma_pa_sink_flags_t;
15174 #define MA_PA_SINK_NOFLAGS 0x00000000
15175 #define MA_PA_SINK_HW_VOLUME_CTRL 0x00000001
15176 #define MA_PA_SINK_LATENCY 0x00000002
15177 #define MA_PA_SINK_HARDWARE 0x00000004
15178 #define MA_PA_SINK_NETWORK 0x00000008
15179 #define MA_PA_SINK_HW_MUTE_CTRL 0x00000010
15180 #define MA_PA_SINK_DECIBEL_VOLUME 0x00000020
15181 #define MA_PA_SINK_FLAT_VOLUME 0x00000040
15182 #define MA_PA_SINK_DYNAMIC_LATENCY 0x00000080
15183 #define MA_PA_SINK_SET_FORMATS 0x00000100
15185 typedef int ma_pa_source_flags_t;
15186 #define MA_PA_SOURCE_NOFLAGS 0x00000000
15187 #define MA_PA_SOURCE_HW_VOLUME_CTRL 0x00000001
15188 #define MA_PA_SOURCE_LATENCY 0x00000002
15189 #define MA_PA_SOURCE_HARDWARE 0x00000004
15190 #define MA_PA_SOURCE_NETWORK 0x00000008
15191 #define MA_PA_SOURCE_HW_MUTE_CTRL 0x00000010
15192 #define MA_PA_SOURCE_DECIBEL_VOLUME 0x00000020
15193 #define MA_PA_SOURCE_DYNAMIC_LATENCY 0x00000040
15194 #define MA_PA_SOURCE_FLAT_VOLUME 0x00000080
15196 typedef int ma_pa_context_state_t;
15197 #define MA_PA_CONTEXT_UNCONNECTED 0
15198 #define MA_PA_CONTEXT_CONNECTING 1
15199 #define MA_PA_CONTEXT_AUTHORIZING 2
15200 #define MA_PA_CONTEXT_SETTING_NAME 3
15201 #define MA_PA_CONTEXT_READY 4
15202 #define MA_PA_CONTEXT_FAILED 5
15203 #define MA_PA_CONTEXT_TERMINATED 6
15205 typedef int ma_pa_stream_state_t;
15206 #define MA_PA_STREAM_UNCONNECTED 0
15207 #define MA_PA_STREAM_CREATING 1
15208 #define MA_PA_STREAM_READY 2
15209 #define MA_PA_STREAM_FAILED 3
15210 #define MA_PA_STREAM_TERMINATED 4
15212 typedef int ma_pa_operation_state_t;
15213 #define MA_PA_OPERATION_RUNNING 0
15214 #define MA_PA_OPERATION_DONE 1
15215 #define MA_PA_OPERATION_CANCELLED 2
15217 typedef int ma_pa_sink_state_t;
15218 #define MA_PA_SINK_INVALID_STATE -1
15219 #define MA_PA_SINK_RUNNING 0
15220 #define MA_PA_SINK_IDLE 1
15221 #define MA_PA_SINK_SUSPENDED 2
15223 typedef int ma_pa_source_state_t;
15224 #define MA_PA_SOURCE_INVALID_STATE -1
15225 #define MA_PA_SOURCE_RUNNING 0
15226 #define MA_PA_SOURCE_IDLE 1
15227 #define MA_PA_SOURCE_SUSPENDED 2
15229 typedef int ma_pa_seek_mode_t;
15230 #define MA_PA_SEEK_RELATIVE 0
15231 #define MA_PA_SEEK_ABSOLUTE 1
15232 #define MA_PA_SEEK_RELATIVE_ON_READ 2
15233 #define MA_PA_SEEK_RELATIVE_END 3
15235 typedef int ma_pa_channel_position_t;
15236 #define MA_PA_CHANNEL_POSITION_INVALID -1
15237 #define MA_PA_CHANNEL_POSITION_MONO 0
15238 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT 1
15239 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT 2
15240 #define MA_PA_CHANNEL_POSITION_FRONT_CENTER 3
15241 #define MA_PA_CHANNEL_POSITION_REAR_CENTER 4
15242 #define MA_PA_CHANNEL_POSITION_REAR_LEFT 5
15243 #define MA_PA_CHANNEL_POSITION_REAR_RIGHT 6
15244 #define MA_PA_CHANNEL_POSITION_LFE 7
15245 #define MA_PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER 8
15246 #define MA_PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER 9
15247 #define MA_PA_CHANNEL_POSITION_SIDE_LEFT 10
15248 #define MA_PA_CHANNEL_POSITION_SIDE_RIGHT 11
15249 #define MA_PA_CHANNEL_POSITION_AUX0 12
15250 #define MA_PA_CHANNEL_POSITION_AUX1 13
15251 #define MA_PA_CHANNEL_POSITION_AUX2 14
15252 #define MA_PA_CHANNEL_POSITION_AUX3 15
15253 #define MA_PA_CHANNEL_POSITION_AUX4 16
15254 #define MA_PA_CHANNEL_POSITION_AUX5 17
15255 #define MA_PA_CHANNEL_POSITION_AUX6 18
15256 #define MA_PA_CHANNEL_POSITION_AUX7 19
15257 #define MA_PA_CHANNEL_POSITION_AUX8 20
15258 #define MA_PA_CHANNEL_POSITION_AUX9 21
15259 #define MA_PA_CHANNEL_POSITION_AUX10 22
15260 #define MA_PA_CHANNEL_POSITION_AUX11 23
15261 #define MA_PA_CHANNEL_POSITION_AUX12 24
15262 #define MA_PA_CHANNEL_POSITION_AUX13 25
15263 #define MA_PA_CHANNEL_POSITION_AUX14 26
15264 #define MA_PA_CHANNEL_POSITION_AUX15 27
15265 #define MA_PA_CHANNEL_POSITION_AUX16 28
15266 #define MA_PA_CHANNEL_POSITION_AUX17 29
15267 #define MA_PA_CHANNEL_POSITION_AUX18 30
15268 #define MA_PA_CHANNEL_POSITION_AUX19 31
15269 #define MA_PA_CHANNEL_POSITION_AUX20 32
15270 #define MA_PA_CHANNEL_POSITION_AUX21 33
15271 #define MA_PA_CHANNEL_POSITION_AUX22 34
15272 #define MA_PA_CHANNEL_POSITION_AUX23 35
15273 #define MA_PA_CHANNEL_POSITION_AUX24 36
15274 #define MA_PA_CHANNEL_POSITION_AUX25 37
15275 #define MA_PA_CHANNEL_POSITION_AUX26 38
15276 #define MA_PA_CHANNEL_POSITION_AUX27 39
15277 #define MA_PA_CHANNEL_POSITION_AUX28 40
15278 #define MA_PA_CHANNEL_POSITION_AUX29 41
15279 #define MA_PA_CHANNEL_POSITION_AUX30 42
15280 #define MA_PA_CHANNEL_POSITION_AUX31 43
15281 #define MA_PA_CHANNEL_POSITION_TOP_CENTER 44
15282 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_LEFT 45
15283 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_RIGHT 46
15284 #define MA_PA_CHANNEL_POSITION_TOP_FRONT_CENTER 47
15285 #define MA_PA_CHANNEL_POSITION_TOP_REAR_LEFT 48
15286 #define MA_PA_CHANNEL_POSITION_TOP_REAR_RIGHT 49
15287 #define MA_PA_CHANNEL_POSITION_TOP_REAR_CENTER 50
15288 #define MA_PA_CHANNEL_POSITION_LEFT MA_PA_CHANNEL_POSITION_FRONT_LEFT
15289 #define MA_PA_CHANNEL_POSITION_RIGHT MA_PA_CHANNEL_POSITION_FRONT_RIGHT
15290 #define MA_PA_CHANNEL_POSITION_CENTER MA_PA_CHANNEL_POSITION_FRONT_CENTER
15291 #define MA_PA_CHANNEL_POSITION_SUBWOOFER MA_PA_CHANNEL_POSITION_LFE
15293 typedef int ma_pa_channel_map_def_t;
15294 #define MA_PA_CHANNEL_MAP_AIFF 0
15295 #define MA_PA_CHANNEL_MAP_ALSA 1
15296 #define MA_PA_CHANNEL_MAP_AUX 2
15297 #define MA_PA_CHANNEL_MAP_WAVEEX 3
15298 #define MA_PA_CHANNEL_MAP_OSS 4
15299 #define MA_PA_CHANNEL_MAP_DEFAULT MA_PA_CHANNEL_MAP_AIFF
15301 typedef int ma_pa_sample_format_t;
15302 #define MA_PA_SAMPLE_INVALID -1
15303 #define MA_PA_SAMPLE_U8 0
15304 #define MA_PA_SAMPLE_ALAW 1
15305 #define MA_PA_SAMPLE_ULAW 2
15306 #define MA_PA_SAMPLE_S16LE 3
15307 #define MA_PA_SAMPLE_S16BE 4
15308 #define MA_PA_SAMPLE_FLOAT32LE 5
15309 #define MA_PA_SAMPLE_FLOAT32BE 6
15310 #define MA_PA_SAMPLE_S32LE 7
15311 #define MA_PA_SAMPLE_S32BE 8
15312 #define MA_PA_SAMPLE_S24LE 9
15313 #define MA_PA_SAMPLE_S24BE 10
15314 #define MA_PA_SAMPLE_S24_32LE 11
15315 #define MA_PA_SAMPLE_S24_32BE 12
15317 typedef struct ma_pa_mainloop ma_pa_mainloop;
15318 typedef struct ma_pa_mainloop_api ma_pa_mainloop_api;
15319 typedef struct ma_pa_context ma_pa_context;
15320 typedef struct ma_pa_operation ma_pa_operation;
15321 typedef struct ma_pa_stream ma_pa_stream;
15322 typedef struct ma_pa_spawn_api ma_pa_spawn_api;
15331 } ma_pa_buffer_attr;
15336 ma_pa_channel_position_t map[MA_PA_CHANNELS_MAX];
15337 } ma_pa_channel_map;
15347 ma_pa_sample_format_t
format;
15350 } ma_pa_sample_spec;
15356 const char* description;
15357 ma_pa_sample_spec sample_spec;
15358 ma_pa_channel_map channel_map;
15360 ma_pa_cvolume volume;
15363 const char* monitor_source_name;
15365 const char* driver;
15366 ma_pa_sink_flags_t
flags;
15370 ma_pa_sink_state_t
state;
15384 const char *description;
15385 ma_pa_sample_spec sample_spec;
15386 ma_pa_channel_map channel_map;
15388 ma_pa_cvolume volume;
15391 const char *monitor_of_sink_name;
15393 const char *driver;
15394 ma_pa_source_flags_t
flags;
15398 ma_pa_source_state_t
state;
15406 } ma_pa_source_info;
15408 typedef void (* ma_pa_context_notify_cb_t)(ma_pa_context* c,
void* userdata);
15409 typedef void (* ma_pa_sink_info_cb_t) (ma_pa_context* c,
const ma_pa_sink_info* i,
int eol,
void* userdata);
15410 typedef void (* ma_pa_source_info_cb_t) (ma_pa_context* c,
const ma_pa_source_info* i,
int eol,
void* userdata);
15411 typedef void (* ma_pa_stream_success_cb_t)(ma_pa_stream* s,
int success,
void* userdata);
15412 typedef void (* ma_pa_stream_request_cb_t)(ma_pa_stream* s,
size_t nbytes,
void* userdata);
15413 typedef void (* ma_pa_free_cb_t) (
void* p);
15417 typedef ma_pa_mainloop* (* ma_pa_mainloop_new_proc) ();
15418 typedef void (* ma_pa_mainloop_free_proc) (ma_pa_mainloop* m);
15419 typedef ma_pa_mainloop_api* (* ma_pa_mainloop_get_api_proc) (ma_pa_mainloop* m);
15420 typedef int (* ma_pa_mainloop_iterate_proc) (ma_pa_mainloop* m,
int block,
int* retval);
15421 typedef void (* ma_pa_mainloop_wakeup_proc) (ma_pa_mainloop* m);
15422 typedef ma_pa_context* (* ma_pa_context_new_proc) (ma_pa_mainloop_api* mainloop,
const char*
name);
15423 typedef void (* ma_pa_context_unref_proc) (ma_pa_context* c);
15424 typedef int (* ma_pa_context_connect_proc) (ma_pa_context* c,
const char* server, ma_pa_context_flags_t
flags,
const ma_pa_spawn_api* api);
15425 typedef void (* ma_pa_context_disconnect_proc) (ma_pa_context* c);
15426 typedef void (* ma_pa_context_set_state_callback_proc) (ma_pa_context* c, ma_pa_context_notify_cb_t cb,
void* userdata);
15427 typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (ma_pa_context* c);
15428 typedef ma_pa_operation* (* ma_pa_context_get_sink_info_list_proc) (ma_pa_context* c, ma_pa_sink_info_cb_t cb,
void* userdata);
15429 typedef ma_pa_operation* (* ma_pa_context_get_source_info_list_proc) (ma_pa_context* c, ma_pa_source_info_cb_t cb,
void* userdata);
15430 typedef ma_pa_operation* (* ma_pa_context_get_sink_info_by_name_proc) (ma_pa_context* c,
const char*
name, ma_pa_sink_info_cb_t cb,
void* userdata);
15431 typedef ma_pa_operation* (* ma_pa_context_get_source_info_by_name_proc)(ma_pa_context* c,
const char*
name, ma_pa_source_info_cb_t cb,
void* userdata);
15432 typedef void (* ma_pa_operation_unref_proc) (ma_pa_operation* o);
15433 typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (ma_pa_operation* o);
15434 typedef ma_pa_channel_map* (* ma_pa_channel_map_init_extend_proc) (ma_pa_channel_map* m,
unsigned channels, ma_pa_channel_map_def_t def);
15435 typedef int (* ma_pa_channel_map_valid_proc) (
const ma_pa_channel_map* m);
15436 typedef int (* ma_pa_channel_map_compatible_proc) (
const ma_pa_channel_map* m,
const ma_pa_sample_spec* ss);
15437 typedef ma_pa_stream* (* ma_pa_stream_new_proc) (ma_pa_context* c,
const char*
name,
const ma_pa_sample_spec* ss,
const ma_pa_channel_map* map);
15438 typedef void (* ma_pa_stream_unref_proc) (ma_pa_stream* s);
15439 typedef int (* ma_pa_stream_connect_playback_proc) (ma_pa_stream* s,
const char* dev,
const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t
flags,
const ma_pa_cvolume* volume, ma_pa_stream* sync_stream);
15440 typedef int (* ma_pa_stream_connect_record_proc) (ma_pa_stream* s,
const char* dev,
const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t
flags);
15441 typedef int (* ma_pa_stream_disconnect_proc) (ma_pa_stream* s);
15442 typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (ma_pa_stream* s);
15443 typedef const ma_pa_sample_spec* (* ma_pa_stream_get_sample_spec_proc) (ma_pa_stream* s);
15444 typedef const ma_pa_channel_map* (* ma_pa_stream_get_channel_map_proc) (ma_pa_stream* s);
15445 typedef const ma_pa_buffer_attr* (* ma_pa_stream_get_buffer_attr_proc) (ma_pa_stream* s);
15446 typedef ma_pa_operation* (* ma_pa_stream_set_buffer_attr_proc) (ma_pa_stream* s,
const ma_pa_buffer_attr* attr, ma_pa_stream_success_cb_t cb,
void* userdata);
15447 typedef const char* (* ma_pa_stream_get_device_name_proc) (ma_pa_stream* s);
15448 typedef void (* ma_pa_stream_set_write_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb,
void* userdata);
15449 typedef void (* ma_pa_stream_set_read_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb,
void* userdata);
15450 typedef ma_pa_operation* (* ma_pa_stream_flush_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb,
void* userdata);
15451 typedef ma_pa_operation* (* ma_pa_stream_drain_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb,
void* userdata);
15452 typedef int (* ma_pa_stream_is_corked_proc) (ma_pa_stream* s);
15453 typedef ma_pa_operation* (* ma_pa_stream_cork_proc) (ma_pa_stream* s,
int b, ma_pa_stream_success_cb_t cb,
void* userdata);
15454 typedef ma_pa_operation* (* ma_pa_stream_trigger_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb,
void* userdata);
15455 typedef int (* ma_pa_stream_begin_write_proc) (ma_pa_stream* s,
void**
data,
size_t* nbytes);
15456 typedef int (* ma_pa_stream_write_proc) (ma_pa_stream* s,
const void*
data,
size_t nbytes, ma_pa_free_cb_t free_cb,
int64_t offset, ma_pa_seek_mode_t seek);
15457 typedef int (* ma_pa_stream_peek_proc) (ma_pa_stream* s,
const void**
data,
size_t* nbytes);
15458 typedef int (* ma_pa_stream_drop_proc) (ma_pa_stream* s);
15459 typedef size_t (* ma_pa_stream_writable_size_proc) (ma_pa_stream* s);
15460 typedef size_t (* ma_pa_stream_readable_size_proc) (ma_pa_stream* s);
15467 } ma_pulse_device_enum_data;
15483 if (ma_is_little_endian()) {
15504 default:
return MA_PA_SAMPLE_INVALID;
15511 if (ma_is_little_endian()) {
15536 ma_channel ma_channel_position_from_pulse(ma_pa_channel_position_t position)
15597 ma_pa_channel_position_t ma_channel_position_to_pulse(
ma_channel position)
15620 case MA_CHANNEL_19:
return MA_PA_CHANNEL_POSITION_AUX18;
15621 case MA_CHANNEL_20:
return MA_PA_CHANNEL_POSITION_AUX19;
15622 case MA_CHANNEL_21:
return MA_PA_CHANNEL_POSITION_AUX20;
15623 case MA_CHANNEL_22:
return MA_PA_CHANNEL_POSITION_AUX21;
15624 case MA_CHANNEL_23:
return MA_PA_CHANNEL_POSITION_AUX22;
15625 case MA_CHANNEL_24:
return MA_PA_CHANNEL_POSITION_AUX23;
15626 case MA_CHANNEL_25:
return MA_PA_CHANNEL_POSITION_AUX24;
15627 case MA_CHANNEL_26:
return MA_PA_CHANNEL_POSITION_AUX25;
15628 case MA_CHANNEL_27:
return MA_PA_CHANNEL_POSITION_AUX26;
15629 case MA_CHANNEL_28:
return MA_PA_CHANNEL_POSITION_AUX27;
15630 case MA_CHANNEL_29:
return MA_PA_CHANNEL_POSITION_AUX28;
15631 case MA_CHANNEL_30:
return MA_PA_CHANNEL_POSITION_AUX29;
15632 case MA_CHANNEL_31:
return MA_PA_CHANNEL_POSITION_AUX30;
15633 case MA_CHANNEL_32:
return MA_PA_CHANNEL_POSITION_AUX31;
15634 default:
return (ma_pa_channel_position_t)position;
15639 ma_result ma_wait_for_operation__pulse(
ma_context* pContext, ma_pa_mainloop* pMainLoop, ma_pa_operation* pOP)
15641 ma_assert(pContext !=
NULL);
15642 ma_assert(pMainLoop !=
NULL);
15643 ma_assert(pOP !=
NULL);
15645 while (((ma_pa_operation_get_state_proc)pContext->pulse.pa_operation_get_state)(pOP) == MA_PA_OPERATION_RUNNING) {
15646 int error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)(pMainLoop, 1,
NULL);
15648 return ma_result_from_pulse(error);
15655 ma_result ma_device__wait_for_operation__pulse(
ma_device* pDevice, ma_pa_operation* pOP)
15657 ma_assert(pDevice !=
NULL);
15658 ma_assert(pOP !=
NULL);
15660 return ma_wait_for_operation__pulse(pDevice->pContext, (ma_pa_mainloop*)pDevice->pulse.pMainLoop, pOP);
15666 ma_assert(pContext !=
NULL);
15667 ma_assert(pID0 !=
NULL);
15668 ma_assert(pID1 !=
NULL);
15671 return ma_strcmp(pID0->pulse, pID1->pulse) == 0;
15681 } ma_context_enumerate_devices_callback_data__pulse;
15683 void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pSinkInfo,
int endOfList,
void* pUserData)
15685 ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
15688 ma_assert(pData !=
NULL);
15690 if (endOfList || pData->isTerminated) {
15694 ma_zero_object(&deviceInfo);
15697 if (pSinkInfo->name !=
NULL) {
15698 ma_strncpy_s(deviceInfo.
id.pulse,
sizeof(deviceInfo.
id.pulse), pSinkInfo->name, (
size_t)-1);
15702 if (pSinkInfo->description !=
NULL) {
15703 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), pSinkInfo->description, (
size_t)-1);
15706 pData->isTerminated = !pData->callback(pData->pContext,
ma_device_type_playback, &deviceInfo, pData->pUserData);
15708 (
void)pPulseContext;
15711 void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_source_info* pSinkInfo,
int endOfList,
void* pUserData)
15713 ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
15716 ma_assert(pData !=
NULL);
15718 if (endOfList || pData->isTerminated) {
15722 ma_zero_object(&deviceInfo);
15725 if (pSinkInfo->name !=
NULL) {
15726 ma_strncpy_s(deviceInfo.
id.pulse,
sizeof(deviceInfo.
id.pulse), pSinkInfo->name, (
size_t)-1);
15730 if (pSinkInfo->description !=
NULL) {
15731 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), pSinkInfo->description, (
size_t)-1);
15734 pData->isTerminated = !pData->callback(pData->pContext,
ma_device_type_capture, &deviceInfo, pData->pUserData);
15736 (
void)pPulseContext;
15742 ma_context_enumerate_devices_callback_data__pulse callbackData;
15743 ma_pa_operation* pOP =
NULL;
15744 ma_pa_mainloop* pMainLoop;
15745 ma_pa_mainloop_api* pAPI;
15746 ma_pa_context* pPulseContext;
15749 ma_assert(pContext !=
NULL);
15750 ma_assert(callback !=
NULL);
15752 callbackData.pContext = pContext;
15753 callbackData.callback = callback;
15755 callbackData.isTerminated =
MA_FALSE;
15757 pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
15758 if (pMainLoop ==
NULL) {
15762 pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
15763 if (pAPI ==
NULL) {
15764 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15768 pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->pulse.pApplicationName);
15769 if (pPulseContext ==
NULL) {
15770 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15774 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->pulse.pServerName, (pContext->pulse.tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN,
NULL);
15775 if (error != MA_PA_OK) {
15776 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
15777 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15778 return ma_result_from_pulse(error);
15782 ma_pa_context_state_t
state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)(pPulseContext);
15783 if (
state == MA_PA_CONTEXT_READY) {
15786 if (
state == MA_PA_CONTEXT_CONNECTING ||
state == MA_PA_CONTEXT_AUTHORIZING ||
state == MA_PA_CONTEXT_SETTING_NAME) {
15787 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)(pMainLoop, 1,
NULL);
15789 result = ma_result_from_pulse(error);
15793 #ifdef MA_DEBUG_OUTPUT
15794 printf(
"[PulseAudio] pa_context_get_state() returned %d. Waiting.\n",
state);
15798 if (
state == MA_PA_CONTEXT_UNCONNECTED ||
state == MA_PA_CONTEXT_FAILED ||
state == MA_PA_CONTEXT_TERMINATED) {
15799 #ifdef MA_DEBUG_OUTPUT
15800 printf(
"[PulseAudio] pa_context_get_state() returned %d. Failed.\n",
state);
15808 if (!callbackData.isTerminated) {
15809 pOP = ((ma_pa_context_get_sink_info_list_proc)pContext->pulse.pa_context_get_sink_info_list)(pPulseContext, ma_context_enumerate_devices_sink_callback__pulse, &callbackData);
15815 result = ma_wait_for_operation__pulse(pContext, pMainLoop, pOP);
15816 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15824 if (!callbackData.isTerminated) {
15825 pOP = ((ma_pa_context_get_source_info_list_proc)pContext->pulse.pa_context_get_source_info_list)(pPulseContext, ma_context_enumerate_devices_source_callback__pulse, &callbackData);
15831 result = ma_wait_for_operation__pulse(pContext, pMainLoop, pOP);
15832 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15839 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
15840 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
15841 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15850 } ma_context_get_device_info_callback_data__pulse;
15852 void ma_context_get_device_info_sink_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pInfo,
int endOfList,
void* pUserData)
15854 ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
15856 if (endOfList > 0) {
15860 ma_assert(pData !=
NULL);
15861 pData->foundDevice =
MA_TRUE;
15863 if (pInfo->name !=
NULL) {
15864 ma_strncpy_s(pData->pDeviceInfo->id.pulse,
sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (
size_t)-1);
15867 if (pInfo->description !=
NULL) {
15868 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pInfo->description, (
size_t)-1);
15871 pData->pDeviceInfo->minChannels = pInfo->sample_spec.channels;
15872 pData->pDeviceInfo->maxChannels = pInfo->sample_spec.channels;
15873 pData->pDeviceInfo->minSampleRate = pInfo->sample_spec.rate;
15874 pData->pDeviceInfo->maxSampleRate = pInfo->sample_spec.rate;
15875 pData->pDeviceInfo->formatCount = 1;
15876 pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format);
15878 (
void)pPulseContext;
15881 void ma_context_get_device_info_source_callback__pulse(ma_pa_context* pPulseContext,
const ma_pa_source_info* pInfo,
int endOfList,
void* pUserData)
15883 ma_context_get_device_info_callback_data__pulse* pData = (ma_context_get_device_info_callback_data__pulse*)pUserData;
15885 if (endOfList > 0) {
15889 ma_assert(pData !=
NULL);
15890 pData->foundDevice =
MA_TRUE;
15892 if (pInfo->name !=
NULL) {
15893 ma_strncpy_s(pData->pDeviceInfo->id.pulse,
sizeof(pData->pDeviceInfo->id.pulse), pInfo->name, (
size_t)-1);
15896 if (pInfo->description !=
NULL) {
15897 ma_strncpy_s(pData->pDeviceInfo->name,
sizeof(pData->pDeviceInfo->name), pInfo->description, (
size_t)-1);
15900 pData->pDeviceInfo->minChannels = pInfo->sample_spec.channels;
15901 pData->pDeviceInfo->maxChannels = pInfo->sample_spec.channels;
15902 pData->pDeviceInfo->minSampleRate = pInfo->sample_spec.rate;
15903 pData->pDeviceInfo->maxSampleRate = pInfo->sample_spec.rate;
15904 pData->pDeviceInfo->formatCount = 1;
15905 pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format);
15907 (
void)pPulseContext;
15913 ma_context_get_device_info_callback_data__pulse callbackData;
15914 ma_pa_operation* pOP =
NULL;
15915 ma_pa_mainloop* pMainLoop;
15916 ma_pa_mainloop_api* pAPI;
15917 ma_pa_context* pPulseContext;
15920 ma_assert(pContext !=
NULL);
15927 callbackData.pDeviceInfo = pDeviceInfo;
15928 callbackData.foundDevice =
MA_FALSE;
15930 pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
15931 if (pMainLoop ==
NULL) {
15935 pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
15936 if (pAPI ==
NULL) {
15937 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15941 pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->pulse.pApplicationName);
15942 if (pPulseContext ==
NULL) {
15943 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15947 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->pulse.pServerName, 0,
NULL);
15948 if (error != MA_PA_OK) {
15949 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
15950 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
15951 return ma_result_from_pulse(error);
15955 ma_pa_context_state_t
state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)(pPulseContext);
15956 if (
state == MA_PA_CONTEXT_READY) {
15959 if (
state == MA_PA_CONTEXT_CONNECTING ||
state == MA_PA_CONTEXT_AUTHORIZING ||
state == MA_PA_CONTEXT_SETTING_NAME) {
15960 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)(pMainLoop, 1,
NULL);
15962 result = ma_result_from_pulse(error);
15966 #ifdef MA_DEBUG_OUTPUT
15967 printf(
"[PulseAudio] pa_context_get_state() returned %d. Waiting.\n",
state);
15971 if (
state == MA_PA_CONTEXT_UNCONNECTED ||
state == MA_PA_CONTEXT_FAILED ||
state == MA_PA_CONTEXT_TERMINATED) {
15972 #ifdef MA_DEBUG_OUTPUT
15973 printf(
"[PulseAudio] pa_context_get_state() returned %d. Failed.\n",
state);
15980 pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)(pPulseContext, pDeviceID->pulse, ma_context_get_device_info_sink_callback__pulse, &callbackData);
15982 pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)(pPulseContext, pDeviceID->pulse, ma_context_get_device_info_source_callback__pulse, &callbackData);
15986 ma_wait_for_operation__pulse(pContext, pMainLoop, pOP);
15987 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
15993 if (!callbackData.foundDevice) {
16000 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
16001 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
16002 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
16007 void ma_pulse_device_state_callback(ma_pa_context* pPulseContext,
void* pUserData)
16013 ma_assert(pDevice !=
NULL);
16015 pContext = pDevice->pContext;
16016 ma_assert(pContext !=
NULL);
16018 pDevice->pulse.pulseContextState = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)(pPulseContext);
16021 void ma_device_sink_info_callback(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pInfo,
int endOfList,
void* pUserData)
16023 ma_pa_sink_info* pInfoOut;
16025 if (endOfList > 0) {
16029 pInfoOut = (ma_pa_sink_info*)pUserData;
16030 ma_assert(pInfoOut !=
NULL);
16032 *pInfoOut = *pInfo;
16034 (
void)pPulseContext;
16037 void ma_device_source_info_callback(ma_pa_context* pPulseContext,
const ma_pa_source_info* pInfo,
int endOfList,
void* pUserData)
16039 ma_pa_source_info* pInfoOut;
16041 if (endOfList > 0) {
16045 pInfoOut = (ma_pa_source_info*)pUserData;
16046 ma_assert(pInfoOut !=
NULL);
16048 *pInfoOut = *pInfo;
16050 (
void)pPulseContext;
16053 void ma_device_sink_name_callback(ma_pa_context* pPulseContext,
const ma_pa_sink_info* pInfo,
int endOfList,
void* pUserData)
16057 if (endOfList > 0) {
16062 ma_assert(pDevice !=
NULL);
16064 ma_strncpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name), pInfo->description, (
size_t)-1);
16066 (
void)pPulseContext;
16069 void ma_device_source_name_callback(ma_pa_context* pPulseContext,
const ma_pa_source_info* pInfo,
int endOfList,
void* pUserData)
16073 if (endOfList > 0) {
16078 ma_assert(pDevice !=
NULL);
16080 ma_strncpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name), pInfo->description, (
size_t)-1);
16082 (
void)pPulseContext;
16085 void ma_device_uninit__pulse(
ma_device* pDevice)
16089 ma_assert(pDevice !=
NULL);
16091 pContext = pDevice->pContext;
16092 ma_assert(pContext !=
NULL);
16095 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16096 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16099 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16100 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16103 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pDevice->pulse.pPulseContext);
16104 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pDevice->pulse.pPulseContext);
16105 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)pDevice->pulse.pMainLoop);
16108 ma_pa_buffer_attr ma_device__pa_buffer_attr_new(
ma_uint32 bufferSizeInFrames,
ma_uint32 periods,
const ma_pa_sample_spec* ss)
16110 ma_pa_buffer_attr attr;
16111 attr.maxlength = bufferSizeInFrames *
ma_get_bytes_per_sample(ma_format_from_pulse(ss->format)) * ss->channels;
16112 attr.tlength = attr.maxlength / periods;
16115 attr.fragsize = attr.maxlength / periods;
16120 ma_pa_stream* ma_device__pa_stream_new__pulse(
ma_device* pDevice,
const char* pStreamName,
const ma_pa_sample_spec* ss,
const ma_pa_channel_map* cmap)
16122 static int g_StreamCounter = 0;
16123 char actualStreamName[256];
16125 if (pStreamName !=
NULL) {
16126 ma_strncpy_s(actualStreamName,
sizeof(actualStreamName), pStreamName, (
size_t)-1);
16128 ma_strcpy_s(actualStreamName,
sizeof(actualStreamName),
"miniaudio:");
16129 ma_itoa_s(g_StreamCounter, actualStreamName + 8,
sizeof(actualStreamName)-8, 10);
16131 g_StreamCounter += 1;
16133 return ((ma_pa_stream_new_proc)pDevice->pContext->pulse.pa_stream_new)((ma_pa_context*)pDevice->pulse.pPulseContext, actualStreamName, ss, cmap);
16140 const char* devPlayback =
NULL;
16141 const char* devCapture =
NULL;
16143 ma_pa_sink_info sinkInfo;
16144 ma_pa_source_info sourceInfo;
16145 ma_pa_operation* pOP =
NULL;
16146 ma_pa_sample_spec ss;
16147 ma_pa_channel_map cmap;
16148 ma_pa_buffer_attr attr;
16149 const ma_pa_sample_spec* pActualSS =
NULL;
16150 const ma_pa_channel_map* pActualCMap =
NULL;
16151 const ma_pa_buffer_attr* pActualAttr =
NULL;
16153 ma_pa_stream_flags_t streamFlags;
16155 ma_assert(pDevice !=
NULL);
16156 ma_zero_object(&pDevice->pulse);
16176 if (bufferSizeInMilliseconds == 0) {
16180 pDevice->pulse.pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
16181 if (pDevice->pulse.pMainLoop ==
NULL) {
16186 pDevice->pulse.pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)((ma_pa_mainloop*)pDevice->pulse.pMainLoop);
16187 if (pDevice->pulse.pAPI ==
NULL) {
16192 pDevice->pulse.pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)((ma_pa_mainloop_api*)pDevice->pulse.pAPI, pContext->pulse.pApplicationName);
16193 if (pDevice->pulse.pPulseContext ==
NULL) {
16198 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pDevice->pulse.pPulseContext, pContext->pulse.pServerName, (pContext->pulse.tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN,
NULL);
16199 if (error != MA_PA_OK) {
16200 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to connect PulseAudio context.", ma_result_from_pulse(error));
16205 pDevice->pulse.pulseContextState = MA_PA_CONTEXT_UNCONNECTED;
16206 ((ma_pa_context_set_state_callback_proc)pContext->pulse.pa_context_set_state_callback)((ma_pa_context*)pDevice->pulse.pPulseContext, ma_pulse_device_state_callback, pDevice);
16210 if (pDevice->pulse.pulseContextState == MA_PA_CONTEXT_READY) {
16215 if (pDevice->pulse.pulseContextState == MA_PA_CONTEXT_FAILED || pDevice->pulse.pulseContextState == MA_PA_CONTEXT_TERMINATED) {
16220 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
16222 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] The PulseAudio main loop returned an error while connecting the PulseAudio context.", ma_result_from_pulse(error));
16228 pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devCapture, ma_device_source_info_callback, &sourceInfo);
16230 ma_device__wait_for_operation__pulse(pDevice, pOP);
16231 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16233 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to retrieve source info for capture device.", ma_result_from_pulse(error));
16237 ss = sourceInfo.sample_spec;
16238 cmap = sourceInfo.channel_map;
16241 pDevice->capture.internalPeriods = pConfig->
periods;
16243 attr = ma_device__pa_buffer_attr_new(pDevice->capture.internalBufferSizeInFrames, pConfig->
periods, &ss);
16244 #ifdef MA_DEBUG_OUTPUT
16245 printf(
"[PulseAudio] Capture attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->capture.internalBufferSizeInFrames);
16248 pDevice->pulse.pStreamCapture = ma_device__pa_stream_new__pulse(pDevice, pConfig->
pulse.
pStreamNameCapture, &ss, &cmap);
16249 if (pDevice->pulse.pStreamCapture ==
NULL) {
16254 streamFlags = MA_PA_STREAM_START_CORKED | MA_PA_STREAM_FIX_FORMAT | MA_PA_STREAM_FIX_RATE | MA_PA_STREAM_FIX_CHANNELS;
16255 if (devCapture !=
NULL) {
16256 streamFlags |= MA_PA_STREAM_DONT_MOVE;
16259 error = ((ma_pa_stream_connect_record_proc)pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags);
16260 if (error != MA_PA_OK) {
16261 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to connect PulseAudio capture stream.", ma_result_from_pulse(error));
16265 while (((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)((ma_pa_stream*)pDevice->pulse.pStreamCapture) != MA_PA_STREAM_READY) {
16266 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
16268 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] The PulseAudio main loop returned an error while connecting the PulseAudio capture stream.", ma_result_from_pulse(error));
16274 pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16275 if (pActualSS !=
NULL) {
16277 if (ss.format != pActualSS->format || ss.channels != pActualSS->channels || ss.rate != pActualSS->rate) {
16278 attr = ma_device__pa_buffer_attr_new(pDevice->capture.internalBufferSizeInFrames, pConfig->
periods, pActualSS);
16280 pOP = ((ma_pa_stream_set_buffer_attr_proc)pContext->pulse.pa_stream_set_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamCapture, &attr,
NULL,
NULL);
16282 ma_device__wait_for_operation__pulse(pDevice, pOP);
16283 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16290 pDevice->capture.internalFormat = ma_format_from_pulse(ss.format);
16291 pDevice->capture.internalChannels = ss.channels;
16292 pDevice->capture.internalSampleRate = ss.rate;
16295 pActualCMap = ((ma_pa_stream_get_channel_map_proc)pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16296 if (pActualCMap !=
NULL) {
16297 cmap = *pActualCMap;
16299 for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
16300 pDevice->capture.internalChannelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
16304 pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16305 if (pActualAttr !=
NULL) {
16306 attr = *pActualAttr;
16308 pDevice->capture.internalBufferSizeInFrames = attr.maxlength / (
ma_get_bytes_per_sample(pDevice->capture.internalFormat) * pDevice->capture.internalChannels);
16309 pDevice->capture.internalPeriods = attr.maxlength / attr.fragsize;
16310 #ifdef MA_DEBUG_OUTPUT
16311 printf(
"[PulseAudio] Capture actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->capture.internalBufferSizeInFrames);
16315 devCapture = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16316 if (devCapture !=
NULL) {
16317 ma_pa_operation* pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devCapture, ma_device_source_name_callback, pDevice);
16319 ma_device__wait_for_operation__pulse(pDevice, pOP);
16320 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16326 pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devPlayback, ma_device_sink_info_callback, &sinkInfo);
16328 ma_device__wait_for_operation__pulse(pDevice, pOP);
16329 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16331 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to retrieve sink info for playback device.", ma_result_from_pulse(error));
16335 ss = sinkInfo.sample_spec;
16336 cmap = sinkInfo.channel_map;
16339 pDevice->playback.internalPeriods = pConfig->
periods;
16341 attr = ma_device__pa_buffer_attr_new(pDevice->playback.internalBufferSizeInFrames, pConfig->
periods, &ss);
16342 #ifdef MA_DEBUG_OUTPUT
16343 printf(
"[PulseAudio] Playback attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->playback.internalBufferSizeInFrames);
16346 pDevice->pulse.pStreamPlayback = ma_device__pa_stream_new__pulse(pDevice, pConfig->
pulse.
pStreamNamePlayback, &ss, &cmap);
16347 if (pDevice->pulse.pStreamPlayback ==
NULL) {
16352 streamFlags = MA_PA_STREAM_START_CORKED | MA_PA_STREAM_FIX_FORMAT | MA_PA_STREAM_FIX_RATE | MA_PA_STREAM_FIX_CHANNELS;
16353 if (devPlayback !=
NULL) {
16354 streamFlags |= MA_PA_STREAM_DONT_MOVE;
16357 error = ((ma_pa_stream_connect_playback_proc)pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, streamFlags,
NULL,
NULL);
16358 if (error != MA_PA_OK) {
16359 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to connect PulseAudio playback stream.", ma_result_from_pulse(error));
16363 while (((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)((ma_pa_stream*)pDevice->pulse.pStreamPlayback) != MA_PA_STREAM_READY) {
16364 error = ((ma_pa_mainloop_iterate_proc)pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
16366 result = ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] The PulseAudio main loop returned an error while connecting the PulseAudio playback stream.", ma_result_from_pulse(error));
16372 pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16373 if (pActualSS !=
NULL) {
16375 if (ss.format != pActualSS->format || ss.channels != pActualSS->channels || ss.rate != pActualSS->rate) {
16376 attr = ma_device__pa_buffer_attr_new(pDevice->playback.internalBufferSizeInFrames, pConfig->
periods, pActualSS);
16378 pOP = ((ma_pa_stream_set_buffer_attr_proc)pContext->pulse.pa_stream_set_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, &attr,
NULL,
NULL);
16380 ma_device__wait_for_operation__pulse(pDevice, pOP);
16381 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16388 pDevice->playback.internalFormat = ma_format_from_pulse(ss.format);
16389 pDevice->playback.internalChannels = ss.channels;
16390 pDevice->playback.internalSampleRate = ss.rate;
16393 pActualCMap = ((ma_pa_stream_get_channel_map_proc)pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16394 if (pActualCMap !=
NULL) {
16395 cmap = *pActualCMap;
16397 for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
16398 pDevice->playback.internalChannelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
16402 pActualAttr = ((ma_pa_stream_get_buffer_attr_proc)pContext->pulse.pa_stream_get_buffer_attr)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16403 if (pActualAttr !=
NULL) {
16404 attr = *pActualAttr;
16406 pDevice->playback.internalBufferSizeInFrames = attr.maxlength / (
ma_get_bytes_per_sample(pDevice->playback.internalFormat) * pDevice->playback.internalChannels);
16407 pDevice->playback.internalPeriods = attr.maxlength / attr.tlength;
16408 #ifdef MA_DEBUG_OUTPUT
16409 printf(
"[PulseAudio] Playback actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalBufferSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->playback.internalBufferSizeInFrames);
16413 devPlayback = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16414 if (devPlayback !=
NULL) {
16415 ma_pa_operation* pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pDevice->pulse.pPulseContext, devPlayback, ma_device_sink_name_callback, pDevice);
16417 ma_device__wait_for_operation__pulse(pDevice, pOP);
16418 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16428 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16432 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16436 ((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16440 ((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16442 on_error3: ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pDevice->pulse.pPulseContext);
16443 on_error2: ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pDevice->pulse.pPulseContext);
16444 on_error1: ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)pDevice->pulse.pMainLoop);
16450 void ma_pulse_operation_complete_callback(ma_pa_stream* pStream,
int success,
void* pUserData)
16453 ma_assert(pIsSuccessful !=
NULL);
16464 ma_pa_stream* pStream;
16465 ma_pa_operation* pOP;
16475 pStream = (ma_pa_stream*)((deviceType ==
ma_device_type_capture) ? pDevice->pulse.pStreamCapture : pDevice->pulse.pStreamPlayback);
16476 ma_assert(pStream !=
NULL);
16478 pOP = ((ma_pa_stream_cork_proc)pContext->pulse.pa_stream_cork)(pStream, cork, ma_pulse_operation_complete_callback, &wasSuccessful);
16483 result = ma_device__wait_for_operation__pulse(pDevice, pOP);
16484 ((ma_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
16487 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] An error occurred while waiting for the PulseAudio stream to cork.",
result);
16490 if (!wasSuccessful) {
16505 ma_pa_operation* pOP;
16507 ma_assert(pDevice !=
NULL);
16518 pOP = ((ma_pa_stream_drain_proc)pDevice->pContext->pulse.pa_stream_drain)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_pulse_operation_complete_callback, &wasSuccessful);
16520 ma_device__wait_for_operation__pulse(pDevice, pOP);
16521 ((ma_pa_operation_unref_proc)pDevice->pContext->pulse.pa_operation_unref)(pOP);
16537 ma_assert(pDevice !=
NULL);
16538 ma_assert(pPCMFrames !=
NULL);
16539 ma_assert(frameCount > 0);
16541 if (pFramesWritten !=
NULL) {
16542 *pFramesWritten = 0;
16545 totalFramesWritten = 0;
16546 while (totalFramesWritten < frameCount) {
16547 if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
16552 if (pDevice->pulse.pMappedBufferPlayback !=
NULL && pDevice->pulse.mappedBufferFramesRemainingPlayback > 0) {
16553 ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
16554 ma_uint32 mappedBufferFramesConsumed = pDevice->pulse.mappedBufferFramesCapacityPlayback - pDevice->pulse.mappedBufferFramesRemainingPlayback;
16556 void* pDst = (
ma_uint8*)pDevice->pulse.pMappedBufferPlayback + (mappedBufferFramesConsumed * bpf);
16557 const void* pSrc = (
const ma_uint8*)pPCMFrames + (totalFramesWritten * bpf);
16558 ma_uint32 framesToCopy = ma_min(pDevice->pulse.mappedBufferFramesRemainingPlayback, (frameCount - totalFramesWritten));
16559 ma_copy_memory(pDst, pSrc, framesToCopy * bpf);
16561 pDevice->pulse.mappedBufferFramesRemainingPlayback -= framesToCopy;
16562 totalFramesWritten += framesToCopy;
16569 if (pDevice->pulse.mappedBufferFramesCapacityPlayback > 0 && pDevice->pulse.mappedBufferFramesRemainingPlayback == 0) {
16570 size_t nbytes = pDevice->pulse.mappedBufferFramesCapacityPlayback * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
16572 int error = ((ma_pa_stream_write_proc)pDevice->pContext->pulse.pa_stream_write)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, pDevice->pulse.pMappedBufferPlayback, nbytes,
NULL, 0, MA_PA_SEEK_RELATIVE);
16574 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to write data to the PulseAudio stream.", ma_result_from_pulse(error));
16577 pDevice->pulse.pMappedBufferPlayback =
NULL;
16578 pDevice->pulse.mappedBufferFramesRemainingPlayback = 0;
16579 pDevice->pulse.mappedBufferFramesCapacityPlayback = 0;
16582 ma_assert(totalFramesWritten <= frameCount);
16583 if (totalFramesWritten == frameCount) {
16589 size_t writableSizeInBytes;
16592 if (((ma_pa_stream_is_corked_proc)pDevice->pContext->pulse.pa_stream_is_corked)((ma_pa_stream*)pDevice->pulse.pStreamPlayback)) {
16596 writableSizeInBytes = ((ma_pa_stream_writable_size_proc)pDevice->pContext->pulse.pa_stream_writable_size)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
16597 if (writableSizeInBytes != (
size_t)-1) {
16599 if (writableSizeInBytes > 0) {
16601 size_t bytesToMap = writableSizeInBytes;
16602 int error = ((ma_pa_stream_begin_write_proc)pDevice->pContext->pulse.pa_stream_begin_write)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, &pDevice->pulse.pMappedBufferPlayback, &bytesToMap);
16604 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to map write buffer.", ma_result_from_pulse(error));
16607 pDevice->pulse.mappedBufferFramesCapacityPlayback = bytesToMap / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
16608 pDevice->pulse.mappedBufferFramesRemainingPlayback = pDevice->pulse.mappedBufferFramesCapacityPlayback;
16613 int error = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 1,
NULL);
16615 return ma_result_from_pulse(error);
16626 if (pFramesWritten !=
NULL) {
16627 *pFramesWritten = totalFramesWritten;
16637 ma_assert(pDevice !=
NULL);
16638 ma_assert(pPCMFrames !=
NULL);
16639 ma_assert(frameCount > 0);
16641 if (pFramesRead !=
NULL) {
16645 totalFramesRead = 0;
16646 while (totalFramesRead < frameCount) {
16647 if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
16652 if (pDevice->pulse.pMappedBufferCapture !=
NULL && pDevice->pulse.mappedBufferFramesRemainingCapture > 0) {
16653 ma_uint32 bpf = ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
16654 ma_uint32 mappedBufferFramesConsumed = pDevice->pulse.mappedBufferFramesCapacityCapture - pDevice->pulse.mappedBufferFramesRemainingCapture;
16656 ma_uint32 framesToCopy = ma_min(pDevice->pulse.mappedBufferFramesRemainingCapture, (frameCount - totalFramesRead));
16657 void* pDst = (
ma_uint8*)pPCMFrames + (totalFramesRead * bpf);
16663 if (pDevice->pulse.pMappedBufferCapture !=
NULL) {
16664 const void* pSrc = (
const ma_uint8*)pDevice->pulse.pMappedBufferCapture + (mappedBufferFramesConsumed * bpf);
16665 ma_copy_memory(pDst, pSrc, framesToCopy * bpf);
16667 ma_zero_memory(pDst, framesToCopy * bpf);
16670 pDevice->pulse.mappedBufferFramesRemainingCapture -= framesToCopy;
16671 totalFramesRead += framesToCopy;
16678 if (pDevice->pulse.mappedBufferFramesCapacityCapture > 0 && pDevice->pulse.mappedBufferFramesRemainingCapture == 0) {
16679 int error = ((ma_pa_stream_drop_proc)pDevice->pContext->pulse.pa_stream_drop)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16681 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to drop fragment.", ma_result_from_pulse(error));
16684 pDevice->pulse.pMappedBufferCapture =
NULL;
16685 pDevice->pulse.mappedBufferFramesRemainingCapture = 0;
16686 pDevice->pulse.mappedBufferFramesCapacityCapture = 0;
16689 ma_assert(totalFramesRead <= frameCount);
16690 if (totalFramesRead == frameCount) {
16696 size_t readableSizeInBytes;
16698 if (ma_device__get_state(pDevice) != MA_STATE_STARTED) {
16703 if (((ma_pa_stream_is_corked_proc)pDevice->pContext->pulse.pa_stream_is_corked)((ma_pa_stream*)pDevice->pulse.pStreamCapture)) {
16707 readableSizeInBytes = ((ma_pa_stream_readable_size_proc)pDevice->pContext->pulse.pa_stream_readable_size)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
16708 if (readableSizeInBytes != (
size_t)-1) {
16710 if (readableSizeInBytes > 0) {
16712 size_t bytesMapped = (size_t)-1;
16713 int error = ((ma_pa_stream_peek_proc)pDevice->pContext->pulse.pa_stream_peek)((ma_pa_stream*)pDevice->pulse.pStreamCapture, &pDevice->pulse.pMappedBufferCapture, &bytesMapped);
16715 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Failed to peek capture buffer.", ma_result_from_pulse(error));
16718 if (pDevice->pulse.pMappedBufferCapture ==
NULL && bytesMapped == 0) {
16720 return ma_post_error(pDevice,
MA_LOG_LEVEL_ERROR,
"[PulseAudio] Nothing available after peeking capture buffer.",
MA_ERROR);
16723 pDevice->pulse.mappedBufferFramesCapacityCapture = bytesMapped / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
16724 pDevice->pulse.mappedBufferFramesRemainingCapture = pDevice->pulse.mappedBufferFramesCapacityCapture;
16735 int error = ((ma_pa_mainloop_iterate_proc)pDevice->pContext->pulse.pa_mainloop_iterate)((ma_pa_mainloop*)pDevice->pulse.pMainLoop, 0,
NULL);
16737 return ma_result_from_pulse(error);
16753 if (pFramesRead !=
NULL) {
16754 *pFramesRead = totalFramesRead;
16765 ma_assert(pDevice !=
NULL);
16782 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
16783 switch (pDevice->type)
16788 ma_uint8 capturedDeviceData[8192];
16789 ma_uint8 playbackDeviceData[8192];
16790 ma_uint32 capturedDeviceDataCapInFrames =
sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
16791 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
16794 ma_uint32 periodSizeInFrames = ma_min(pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods, pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods);
16796 while (totalFramesProcessed < periodSizeInFrames) {
16797 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
16799 ma_uint32 framesToProcess = framesRemaining;
16800 if (framesToProcess > capturedDeviceDataCapInFrames) {
16801 framesToProcess = capturedDeviceDataCapInFrames;
16804 result = ma_device_read__pulse(pDevice, capturedDeviceData, framesToProcess, &framesProcessed);
16810 pDevice->capture._dspFrameCount = framesToProcess;
16811 pDevice->capture._dspFrames = capturedDeviceData;
16816 ma_uint32 capturedDataCapInFrames =
sizeof(capturedData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
16817 ma_uint32 playbackDataCapInFrames =
sizeof(playbackData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
16819 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
16821 if (capturedFramesToProcess == 0) {
16825 ma_device__on_data(pDevice, playbackData, capturedData, capturedFramesToProcess);
16828 pDevice->playback._dspFrameCount = capturedFramesToProcess;
16829 pDevice->playback._dspFrames = playbackData;
16832 if (playbackDeviceFramesCount == 0) {
16836 result = ma_device_write__pulse(pDevice, playbackDeviceData, playbackDeviceFramesCount,
NULL);
16842 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
16847 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
16858 totalFramesProcessed += framesProcessed;
16864 ma_uint8 intermediaryBuffer[8192];
16865 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
16866 ma_uint32 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
16868 while (framesReadThisPeriod < periodSizeInFrames) {
16869 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
16871 ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
16872 if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
16873 framesToReadThisIteration = intermediaryBufferSizeInFrames;
16876 result = ma_device_read__pulse(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
16882 ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
16884 framesReadThisPeriod += framesProcessed;
16890 ma_uint8 intermediaryBuffer[8192];
16891 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
16892 ma_uint32 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
16894 while (framesWrittenThisPeriod < periodSizeInFrames) {
16895 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
16897 ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
16898 if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
16899 framesToWriteThisIteration = intermediaryBufferSizeInFrames;
16902 ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
16904 result = ma_device_write__pulse(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
16910 framesWrittenThisPeriod += framesProcessed;
16921 ma_device_stop__pulse(pDevice);
16929 ma_assert(pContext !=
NULL);
16932 ma_free(pContext->pulse.pServerName);
16933 pContext->pulse.pServerName =
NULL;
16935 ma_free(pContext->pulse.pApplicationName);
16936 pContext->pulse.pApplicationName =
NULL;
16938 #ifndef MA_NO_RUNTIME_LINKING
16939 ma_dlclose(pContext, pContext->pulse.pulseSO);
16947 #ifndef MA_NO_RUNTIME_LINKING
16948 const char* libpulseNames[] = {
16954 for (i = 0; i < ma_countof(libpulseNames); ++i) {
16955 pContext->pulse.pulseSO = ma_dlopen(pContext, libpulseNames[i]);
16956 if (pContext->pulse.pulseSO !=
NULL) {
16961 if (pContext->pulse.pulseSO ==
NULL) {
16965 pContext->pulse.pa_mainloop_new = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_new");
16966 pContext->pulse.pa_mainloop_free = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_free");
16967 pContext->pulse.pa_mainloop_get_api = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_get_api");
16968 pContext->pulse.pa_mainloop_iterate = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_iterate");
16969 pContext->pulse.pa_mainloop_wakeup = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_mainloop_wakeup");
16970 pContext->pulse.pa_context_new = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_new");
16971 pContext->pulse.pa_context_unref = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_unref");
16972 pContext->pulse.pa_context_connect = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_connect");
16973 pContext->pulse.pa_context_disconnect = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_disconnect");
16974 pContext->pulse.pa_context_set_state_callback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_set_state_callback");
16975 pContext->pulse.pa_context_get_state = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_state");
16976 pContext->pulse.pa_context_get_sink_info_list = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_sink_info_list");
16977 pContext->pulse.pa_context_get_source_info_list = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_source_info_list");
16978 pContext->pulse.pa_context_get_sink_info_by_name = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_sink_info_by_name");
16979 pContext->pulse.pa_context_get_source_info_by_name = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_context_get_source_info_by_name");
16980 pContext->pulse.pa_operation_unref = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_operation_unref");
16981 pContext->pulse.pa_operation_get_state = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_operation_get_state");
16982 pContext->pulse.pa_channel_map_init_extend = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_channel_map_init_extend");
16983 pContext->pulse.pa_channel_map_valid = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_channel_map_valid");
16984 pContext->pulse.pa_channel_map_compatible = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_channel_map_compatible");
16985 pContext->pulse.pa_stream_new = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_new");
16986 pContext->pulse.pa_stream_unref = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_unref");
16987 pContext->pulse.pa_stream_connect_playback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_connect_playback");
16988 pContext->pulse.pa_stream_connect_record = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_connect_record");
16989 pContext->pulse.pa_stream_disconnect = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_disconnect");
16990 pContext->pulse.pa_stream_get_state = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_state");
16991 pContext->pulse.pa_stream_get_sample_spec = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_sample_spec");
16992 pContext->pulse.pa_stream_get_channel_map = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_channel_map");
16993 pContext->pulse.pa_stream_get_buffer_attr = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_buffer_attr");
16994 pContext->pulse.pa_stream_set_buffer_attr = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_set_buffer_attr");
16995 pContext->pulse.pa_stream_get_device_name = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_get_device_name");
16996 pContext->pulse.pa_stream_set_write_callback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_set_write_callback");
16997 pContext->pulse.pa_stream_set_read_callback = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_set_read_callback");
16998 pContext->pulse.pa_stream_flush = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_flush");
16999 pContext->pulse.pa_stream_drain = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_drain");
17000 pContext->pulse.pa_stream_is_corked = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_is_corked");
17001 pContext->pulse.pa_stream_cork = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_cork");
17002 pContext->pulse.pa_stream_trigger = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_trigger");
17003 pContext->pulse.pa_stream_begin_write = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_begin_write");
17004 pContext->pulse.pa_stream_write = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_write");
17005 pContext->pulse.pa_stream_peek = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_peek");
17006 pContext->pulse.pa_stream_drop = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_drop");
17007 pContext->pulse.pa_stream_writable_size = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_writable_size");
17008 pContext->pulse.pa_stream_readable_size = (
ma_proc)ma_dlsym(pContext, pContext->pulse.pulseSO,
"pa_stream_readable_size");
17011 ma_pa_mainloop_new_proc _pa_mainloop_new = pa_mainloop_new;
17012 ma_pa_mainloop_free_proc _pa_mainloop_free = pa_mainloop_free;
17013 ma_pa_mainloop_get_api_proc _pa_mainloop_get_api = pa_mainloop_get_api;
17014 ma_pa_mainloop_iterate_proc _pa_mainloop_iterate = pa_mainloop_iterate;
17015 ma_pa_mainloop_wakeup_proc _pa_mainloop_wakeup = pa_mainloop_wakeup;
17016 ma_pa_context_new_proc _pa_context_new = pa_context_new;
17017 ma_pa_context_unref_proc _pa_context_unref = pa_context_unref;
17018 ma_pa_context_connect_proc _pa_context_connect = pa_context_connect;
17019 ma_pa_context_disconnect_proc _pa_context_disconnect = pa_context_disconnect;
17020 ma_pa_context_set_state_callback_proc _pa_context_set_state_callback = pa_context_set_state_callback;
17021 ma_pa_context_get_state_proc _pa_context_get_state = pa_context_get_state;
17022 ma_pa_context_get_sink_info_list_proc _pa_context_get_sink_info_list = pa_context_get_sink_info_list;
17023 ma_pa_context_get_source_info_list_proc _pa_context_get_source_info_list = pa_context_get_source_info_list;
17024 ma_pa_context_get_sink_info_by_name_proc _pa_context_get_sink_info_by_name = pa_context_get_sink_info_by_name;
17025 ma_pa_context_get_source_info_by_name_proc _pa_context_get_source_info_by_name= pa_context_get_source_info_by_name;
17026 ma_pa_operation_unref_proc _pa_operation_unref = pa_operation_unref;
17027 ma_pa_operation_get_state_proc _pa_operation_get_state = pa_operation_get_state;
17028 ma_pa_channel_map_init_extend_proc _pa_channel_map_init_extend = pa_channel_map_init_extend;
17029 ma_pa_channel_map_valid_proc _pa_channel_map_valid = pa_channel_map_valid;
17030 ma_pa_channel_map_compatible_proc _pa_channel_map_compatible = pa_channel_map_compatible;
17031 ma_pa_stream_new_proc _pa_stream_new = pa_stream_new;
17032 ma_pa_stream_unref_proc _pa_stream_unref = pa_stream_unref;
17033 ma_pa_stream_connect_playback_proc _pa_stream_connect_playback = pa_stream_connect_playback;
17034 ma_pa_stream_connect_record_proc _pa_stream_connect_record = pa_stream_connect_record;
17035 ma_pa_stream_disconnect_proc _pa_stream_disconnect = pa_stream_disconnect;
17036 ma_pa_stream_get_state_proc _pa_stream_get_state = pa_stream_get_state;
17037 ma_pa_stream_get_sample_spec_proc _pa_stream_get_sample_spec = pa_stream_get_sample_spec;
17038 ma_pa_stream_get_channel_map_proc _pa_stream_get_channel_map = pa_stream_get_channel_map;
17039 ma_pa_stream_get_buffer_attr_proc _pa_stream_get_buffer_attr = pa_stream_get_buffer_attr;
17040 ma_pa_stream_set_buffer_attr_proc _pa_stream_set_buffer_attr = pa_stream_set_buffer_attr;
17041 ma_pa_stream_get_device_name_proc _pa_stream_get_device_name = pa_stream_get_device_name;
17042 ma_pa_stream_set_write_callback_proc _pa_stream_set_write_callback = pa_stream_set_write_callback;
17043 ma_pa_stream_set_read_callback_proc _pa_stream_set_read_callback = pa_stream_set_read_callback;
17044 ma_pa_stream_flush_proc _pa_stream_flush = pa_stream_flush;
17045 ma_pa_stream_drain_proc _pa_stream_drain = pa_stream_drain;
17046 ma_pa_stream_is_corked_proc _pa_stream_is_corked = pa_stream_is_corked;
17047 ma_pa_stream_cork_proc _pa_stream_cork = pa_stream_cork;
17048 ma_pa_stream_trigger_proc _pa_stream_trigger = pa_stream_trigger;
17049 ma_pa_stream_begin_write_proc _pa_stream_begin_write = pa_stream_begin_write;
17050 ma_pa_stream_write_proc _pa_stream_write = pa_stream_write;
17051 ma_pa_stream_peek_proc _pa_stream_peek = pa_stream_peek;
17052 ma_pa_stream_drop_proc _pa_stream_drop = pa_stream_drop;
17053 ma_pa_stream_writable_size_proc _pa_stream_writable_size = pa_stream_writable_size;
17054 ma_pa_stream_readable_size_proc _pa_stream_readable_size = pa_stream_readable_size;
17056 pContext->pulse.pa_mainloop_new = (
ma_proc)_pa_mainloop_new;
17057 pContext->pulse.pa_mainloop_free = (
ma_proc)_pa_mainloop_free;
17058 pContext->pulse.pa_mainloop_get_api = (
ma_proc)_pa_mainloop_get_api;
17059 pContext->pulse.pa_mainloop_iterate = (
ma_proc)_pa_mainloop_iterate;
17060 pContext->pulse.pa_mainloop_wakeup = (
ma_proc)_pa_mainloop_wakeup;
17061 pContext->pulse.pa_context_new = (
ma_proc)_pa_context_new;
17062 pContext->pulse.pa_context_unref = (
ma_proc)_pa_context_unref;
17063 pContext->pulse.pa_context_connect = (
ma_proc)_pa_context_connect;
17064 pContext->pulse.pa_context_disconnect = (
ma_proc)_pa_context_disconnect;
17065 pContext->pulse.pa_context_set_state_callback = (
ma_proc)_pa_context_set_state_callback;
17066 pContext->pulse.pa_context_get_state = (
ma_proc)_pa_context_get_state;
17067 pContext->pulse.pa_context_get_sink_info_list = (
ma_proc)_pa_context_get_sink_info_list;
17068 pContext->pulse.pa_context_get_source_info_list = (
ma_proc)_pa_context_get_source_info_list;
17069 pContext->pulse.pa_context_get_sink_info_by_name = (
ma_proc)_pa_context_get_sink_info_by_name;
17070 pContext->pulse.pa_context_get_source_info_by_name = (
ma_proc)_pa_context_get_source_info_by_name;
17071 pContext->pulse.pa_operation_unref = (
ma_proc)_pa_operation_unref;
17072 pContext->pulse.pa_operation_get_state = (
ma_proc)_pa_operation_get_state;
17073 pContext->pulse.pa_channel_map_init_extend = (
ma_proc)_pa_channel_map_init_extend;
17074 pContext->pulse.pa_channel_map_valid = (
ma_proc)_pa_channel_map_valid;
17075 pContext->pulse.pa_channel_map_compatible = (
ma_proc)_pa_channel_map_compatible;
17076 pContext->pulse.pa_stream_new = (
ma_proc)_pa_stream_new;
17077 pContext->pulse.pa_stream_unref = (
ma_proc)_pa_stream_unref;
17078 pContext->pulse.pa_stream_connect_playback = (
ma_proc)_pa_stream_connect_playback;
17079 pContext->pulse.pa_stream_connect_record = (
ma_proc)_pa_stream_connect_record;
17080 pContext->pulse.pa_stream_disconnect = (
ma_proc)_pa_stream_disconnect;
17081 pContext->pulse.pa_stream_get_state = (
ma_proc)_pa_stream_get_state;
17082 pContext->pulse.pa_stream_get_sample_spec = (
ma_proc)_pa_stream_get_sample_spec;
17083 pContext->pulse.pa_stream_get_channel_map = (
ma_proc)_pa_stream_get_channel_map;
17084 pContext->pulse.pa_stream_get_buffer_attr = (
ma_proc)_pa_stream_get_buffer_attr;
17085 pContext->pulse.pa_stream_set_buffer_attr = (
ma_proc)_pa_stream_set_buffer_attr;
17086 pContext->pulse.pa_stream_get_device_name = (
ma_proc)_pa_stream_get_device_name;
17087 pContext->pulse.pa_stream_set_write_callback = (
ma_proc)_pa_stream_set_write_callback;
17088 pContext->pulse.pa_stream_set_read_callback = (
ma_proc)_pa_stream_set_read_callback;
17089 pContext->pulse.pa_stream_flush = (
ma_proc)_pa_stream_flush;
17090 pContext->pulse.pa_stream_drain = (
ma_proc)_pa_stream_drain;
17091 pContext->pulse.pa_stream_is_corked = (
ma_proc)_pa_stream_is_corked;
17092 pContext->pulse.pa_stream_cork = (
ma_proc)_pa_stream_cork;
17093 pContext->pulse.pa_stream_trigger = (
ma_proc)_pa_stream_trigger;
17094 pContext->pulse.pa_stream_begin_write = (
ma_proc)_pa_stream_begin_write;
17095 pContext->pulse.pa_stream_write = (
ma_proc)_pa_stream_write;
17096 pContext->pulse.pa_stream_peek = (
ma_proc)_pa_stream_peek;
17097 pContext->pulse.pa_stream_drop = (
ma_proc)_pa_stream_drop;
17098 pContext->pulse.pa_stream_writable_size = (
ma_proc)_pa_stream_writable_size;
17099 pContext->pulse.pa_stream_readable_size = (
ma_proc)_pa_stream_readable_size;
17102 pContext->
onUninit = ma_context_uninit__pulse;
17104 pContext->
onEnumDevices = ma_context_enumerate_devices__pulse;
17125 ma_pa_mainloop* pMainLoop;
17126 ma_pa_mainloop_api* pAPI;
17127 ma_pa_context* pPulseContext;
17130 pMainLoop = ((ma_pa_mainloop_new_proc)pContext->pulse.pa_mainloop_new)();
17131 if (pMainLoop ==
NULL) {
17132 ma_free(pContext->pulse.pServerName);
17133 ma_free(pContext->pulse.pApplicationName);
17134 #ifndef MA_NO_RUNTIME_LINKING
17135 ma_dlclose(pContext, pContext->pulse.pulseSO);
17140 pAPI = ((ma_pa_mainloop_get_api_proc)pContext->pulse.pa_mainloop_get_api)(pMainLoop);
17141 if (pAPI ==
NULL) {
17142 ma_free(pContext->pulse.pServerName);
17143 ma_free(pContext->pulse.pApplicationName);
17144 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
17145 #ifndef MA_NO_RUNTIME_LINKING
17146 ma_dlclose(pContext, pContext->pulse.pulseSO);
17151 pPulseContext = ((ma_pa_context_new_proc)pContext->pulse.pa_context_new)(pAPI, pContext->pulse.pApplicationName);
17152 if (pPulseContext ==
NULL) {
17153 ma_free(pContext->pulse.pServerName);
17154 ma_free(pContext->pulse.pApplicationName);
17155 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
17156 #ifndef MA_NO_RUNTIME_LINKING
17157 ma_dlclose(pContext, pContext->pulse.pulseSO);
17162 error = ((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)(pPulseContext, pContext->pulse.pServerName, 0,
NULL);
17163 if (error != MA_PA_OK) {
17164 ma_free(pContext->pulse.pServerName);
17165 ma_free(pContext->pulse.pApplicationName);
17166 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
17167 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
17168 #ifndef MA_NO_RUNTIME_LINKING
17169 ma_dlclose(pContext, pContext->pulse.pulseSO);
17174 ((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)(pPulseContext);
17175 ((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)(pPulseContext);
17176 ((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)(pMainLoop);
17192 #ifdef MA_NO_RUNTIME_LINKING
17193 #include <jack/jack.h>
17195 typedef jack_nframes_t ma_jack_nframes_t;
17196 typedef jack_options_t ma_jack_options_t;
17197 typedef jack_status_t ma_jack_status_t;
17198 typedef jack_client_t ma_jack_client_t;
17199 typedef jack_port_t ma_jack_port_t;
17200 typedef JackProcessCallback ma_JackProcessCallback;
17201 typedef JackBufferSizeCallback ma_JackBufferSizeCallback;
17202 typedef JackShutdownCallback ma_JackShutdownCallback;
17203 #define MA_JACK_DEFAULT_AUDIO_TYPE JACK_DEFAULT_AUDIO_TYPE
17204 #define ma_JackNoStartServer JackNoStartServer
17205 #define ma_JackPortIsInput JackPortIsInput
17206 #define ma_JackPortIsOutput JackPortIsOutput
17207 #define ma_JackPortIsPhysical JackPortIsPhysical
17210 typedef int ma_jack_options_t;
17211 typedef int ma_jack_status_t;
17212 typedef struct ma_jack_client_t ma_jack_client_t;
17213 typedef struct ma_jack_port_t ma_jack_port_t;
17214 typedef int (* ma_JackProcessCallback) (ma_jack_nframes_t nframes,
void* arg);
17215 typedef int (* ma_JackBufferSizeCallback)(ma_jack_nframes_t nframes,
void* arg);
17216 typedef void (* ma_JackShutdownCallback) (
void* arg);
17217 #define MA_JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio"
17218 #define ma_JackNoStartServer 1
17219 #define ma_JackPortIsInput 1
17220 #define ma_JackPortIsOutput 2
17221 #define ma_JackPortIsPhysical 4
17224 typedef ma_jack_client_t* (* ma_jack_client_open_proc) (
const char* client_name, ma_jack_options_t options, ma_jack_status_t* status, ...);
17225 typedef int (* ma_jack_client_close_proc) (ma_jack_client_t* client);
17226 typedef int (* ma_jack_client_name_size_proc) ();
17227 typedef int (* ma_jack_set_process_callback_proc) (ma_jack_client_t* client, ma_JackProcessCallback process_callback,
void* arg);
17228 typedef int (* ma_jack_set_buffer_size_callback_proc)(ma_jack_client_t* client, ma_JackBufferSizeCallback bufsize_callback,
void* arg);
17229 typedef void (* ma_jack_on_shutdown_proc) (ma_jack_client_t* client, ma_JackShutdownCallback
function,
void* arg);
17230 typedef ma_jack_nframes_t (* ma_jack_get_sample_rate_proc) (ma_jack_client_t* client);
17231 typedef ma_jack_nframes_t (* ma_jack_get_buffer_size_proc) (ma_jack_client_t* client);
17232 typedef const char** (* ma_jack_get_ports_proc) (ma_jack_client_t* client,
const char* port_name_pattern,
const char* type_name_pattern,
unsigned long flags);
17233 typedef int (* ma_jack_activate_proc) (ma_jack_client_t* client);
17234 typedef int (* ma_jack_deactivate_proc) (ma_jack_client_t* client);
17235 typedef int (* ma_jack_connect_proc) (ma_jack_client_t* client,
const char* source_port,
const char* destination_port);
17236 typedef ma_jack_port_t* (* ma_jack_port_register_proc) (ma_jack_client_t* client,
const char* port_name,
const char* port_type,
unsigned long flags,
unsigned long buffer_size);
17237 typedef const char* (* ma_jack_port_name_proc) (
const ma_jack_port_t*
port);
17238 typedef void* (* ma_jack_port_get_buffer_proc) (ma_jack_port_t*
port, ma_jack_nframes_t nframes);
17239 typedef void (* ma_jack_free_proc) (
void* ptr);
17241 ma_result ma_context_open_client__jack(
ma_context* pContext, ma_jack_client_t** ppClient)
17243 size_t maxClientNameSize;
17244 char clientName[256];
17245 ma_jack_status_t status;
17246 ma_jack_client_t* pClient;
17248 ma_assert(pContext !=
NULL);
17249 ma_assert(ppClient !=
NULL);
17255 maxClientNameSize = ((ma_jack_client_name_size_proc)pContext->jack.jack_client_name_size)();
17256 ma_strncpy_s(clientName, ma_min(
sizeof(clientName), maxClientNameSize), (pContext->jack.pClientName !=
NULL) ? pContext->jack.pClientName :
"miniaudio", (
size_t)-1);
17258 pClient = ((ma_jack_client_open_proc)pContext->jack.jack_client_open)(clientName, (pContext->jack.tryStartServer) ? 0 : ma_JackNoStartServer, &status,
NULL);
17259 if (pClient ==
NULL) {
17264 *ppClient = pClient;
17272 ma_assert(pContext !=
NULL);
17273 ma_assert(pID0 !=
NULL);
17274 ma_assert(pID1 !=
NULL);
17277 return pID0->jack == pID1->jack;
17284 ma_assert(pContext !=
NULL);
17285 ma_assert(callback !=
NULL);
17290 ma_zero_object(&deviceInfo);
17291 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
17298 ma_zero_object(&deviceInfo);
17299 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
17308 ma_jack_client_t* pClient;
17310 const char** ppPorts;
17312 ma_assert(pContext !=
NULL);
17319 if (pDeviceID !=
NULL && pDeviceID->jack != 0) {
17325 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
17327 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
17335 result = ma_context_open_client__jack(pContext, &pClient);
17340 pDeviceInfo->
minSampleRate = ((ma_jack_get_sample_rate_proc)pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pClient);
17346 ppPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pClient,
NULL,
NULL, ma_JackPortIsPhysical | ((deviceType ==
ma_device_type_playback) ? ma_JackPortIsInput : ma_JackPortIsOutput));
17347 if (ppPorts ==
NULL) {
17348 ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pClient);
17357 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppPorts);
17358 ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pClient);
17365 void ma_device_uninit__jack(
ma_device* pDevice)
17369 ma_assert(pDevice !=
NULL);
17371 pContext = pDevice->pContext;
17372 ma_assert(pContext !=
NULL);
17374 if (pDevice->jack.pClient !=
NULL) {
17375 ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pDevice->jack.pClient);
17379 ma_free(pDevice->jack.pIntermediaryBufferCapture);
17383 ma_free(pDevice->jack.pIntermediaryBufferPlayback);
17391 void ma_device__jack_shutdown_callback(
void* pUserData)
17395 ma_assert(pDevice !=
NULL);
17400 int ma_device__jack_buffer_size_callback(ma_jack_nframes_t frameCount,
void* pUserData)
17403 ma_assert(pDevice !=
NULL);
17406 float* pNewBuffer = (
float*)
ma_realloc(pDevice->jack.pIntermediaryBufferCapture, frameCount * (pDevice->capture.internalChannels *
ma_get_bytes_per_sample(pDevice->capture.internalFormat)));
17407 if (pNewBuffer ==
NULL) {
17411 pDevice->jack.pIntermediaryBufferCapture = pNewBuffer;
17412 pDevice->playback.internalBufferSizeInFrames = frameCount * pDevice->capture.internalPeriods;
17416 float* pNewBuffer = (
float*)
ma_realloc(pDevice->jack.pIntermediaryBufferPlayback, frameCount * (pDevice->playback.internalChannels *
ma_get_bytes_per_sample(pDevice->playback.internalFormat)));
17417 if (pNewBuffer ==
NULL) {
17421 pDevice->jack.pIntermediaryBufferPlayback = pNewBuffer;
17422 pDevice->playback.internalBufferSizeInFrames = frameCount * pDevice->playback.internalPeriods;
17428 int ma_device__jack_process_callback(ma_jack_nframes_t frameCount,
void* pUserData)
17435 ma_assert(pDevice !=
NULL);
17437 pContext = pDevice->pContext;
17438 ma_assert(pContext !=
NULL);
17442 for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
17443 const float* pSrc = (
const float*)((ma_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((ma_jack_port_t*)pDevice->jack.pPortsCapture[iChannel], frameCount);
17444 if (pSrc !=
NULL) {
17445 float* pDst = pDevice->jack.pIntermediaryBufferCapture + iChannel;
17446 ma_jack_nframes_t iFrame;
17447 for (iFrame = 0; iFrame < frameCount; ++iFrame) {
17450 pDst += pDevice->capture.internalChannels;
17457 ma_device__handle_duplex_callback_capture(pDevice, frameCount, pDevice->jack.pIntermediaryBufferCapture, &pDevice->jack.duplexRB);
17459 ma_device__send_frames_to_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferCapture);
17465 ma_device__handle_duplex_callback_playback(pDevice, frameCount, pDevice->jack.pIntermediaryBufferPlayback, &pDevice->jack.duplexRB);
17467 ma_device__read_frames_from_client(pDevice, frameCount, pDevice->jack.pIntermediaryBufferPlayback);
17471 for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
17472 float* pDst = (
float*)((ma_jack_port_get_buffer_proc)pContext->jack.jack_port_get_buffer)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[iChannel], frameCount);
17473 if (pDst !=
NULL) {
17474 const float* pSrc = pDevice->jack.pIntermediaryBufferPlayback + iChannel;
17475 ma_jack_nframes_t iFrame;
17476 for (iFrame = 0; iFrame < frameCount; ++iFrame) {
17480 pSrc += pDevice->playback.internalChannels;
17495 ma_assert(pContext !=
NULL);
17496 ma_assert(pConfig !=
NULL);
17497 ma_assert(pDevice !=
NULL);
17516 result = ma_context_open_client__jack(pContext, (ma_jack_client_t**)&pDevice->jack.pClient);
17522 if (((ma_jack_set_process_callback_proc)pContext->jack.jack_set_process_callback)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_process_callback, pDevice) != 0) {
17525 if (((ma_jack_set_buffer_size_callback_proc)pContext->jack.jack_set_buffer_size_callback)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_buffer_size_callback, pDevice) != 0) {
17529 ((ma_jack_on_shutdown_proc)pContext->jack.jack_on_shutdown)((ma_jack_client_t*)pDevice->jack.pClient, ma_device__jack_shutdown_callback, pDevice);
17534 bufferSizeInFrames = ((ma_jack_get_buffer_size_proc)pContext->jack.jack_get_buffer_size)((ma_jack_client_t*)pDevice->jack.pClient) * periods;
17537 const char** ppPorts;
17540 pDevice->capture.internalChannels = 0;
17541 pDevice->capture.internalSampleRate = ((ma_jack_get_sample_rate_proc)pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
17544 ppPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsOutput);
17545 if (ppPorts ==
NULL) {
17549 while (ppPorts[pDevice->capture.internalChannels] !=
NULL) {
17551 ma_strcpy_s(
name,
sizeof(
name),
"capture");
17552 ma_itoa_s((
int)pDevice->capture.internalChannels,
name+7,
sizeof(
name)-7, 10);
17554 pDevice->jack.pPortsCapture[pDevice->capture.internalChannels] = ((ma_jack_port_register_proc)pContext->jack.jack_port_register)((ma_jack_client_t*)pDevice->jack.pClient,
name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsInput, 0);
17555 if (pDevice->jack.pPortsCapture[pDevice->capture.internalChannels] ==
NULL) {
17556 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppPorts);
17557 ma_device_uninit__jack(pDevice);
17561 pDevice->capture.internalChannels += 1;
17564 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppPorts);
17566 pDevice->capture.internalBufferSizeInFrames = bufferSizeInFrames;
17567 pDevice->capture.internalPeriods = periods;
17569 pDevice->jack.pIntermediaryBufferCapture = (
float*)
ma_malloc((pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods) * (pDevice->capture.internalChannels *
ma_get_bytes_per_sample(pDevice->capture.internalFormat)));
17570 if (pDevice->jack.pIntermediaryBufferCapture ==
NULL) {
17571 ma_device_uninit__jack(pDevice);
17577 const char** ppPorts;
17580 pDevice->playback.internalChannels = 0;
17581 pDevice->playback.internalSampleRate = ((ma_jack_get_sample_rate_proc)pContext->jack.jack_get_sample_rate)((ma_jack_client_t*)pDevice->jack.pClient);
17584 ppPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsInput);
17585 if (ppPorts ==
NULL) {
17589 while (ppPorts[pDevice->playback.internalChannels] !=
NULL) {
17591 ma_strcpy_s(
name,
sizeof(
name),
"playback");
17592 ma_itoa_s((
int)pDevice->playback.internalChannels,
name+8,
sizeof(
name)-8, 10);
17594 pDevice->jack.pPortsPlayback[pDevice->playback.internalChannels] = ((ma_jack_port_register_proc)pContext->jack.jack_port_register)((ma_jack_client_t*)pDevice->jack.pClient,
name, MA_JACK_DEFAULT_AUDIO_TYPE, ma_JackPortIsOutput, 0);
17595 if (pDevice->jack.pPortsPlayback[pDevice->playback.internalChannels] ==
NULL) {
17596 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppPorts);
17597 ma_device_uninit__jack(pDevice);
17601 pDevice->playback.internalChannels += 1;
17604 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppPorts);
17606 pDevice->playback.internalBufferSizeInFrames = bufferSizeInFrames;
17607 pDevice->playback.internalPeriods = periods;
17609 pDevice->jack.pIntermediaryBufferPlayback = (
float*)
ma_malloc((pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods) * (pDevice->playback.internalChannels *
ma_get_bytes_per_sample(pDevice->playback.internalFormat)));
17610 if (pDevice->jack.pIntermediaryBufferPlayback ==
NULL) {
17611 ma_device_uninit__jack(pDevice);
17617 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
17618 result =
ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames,
NULL, &pDevice->jack.duplexRB);
17620 ma_device_uninit__jack(pDevice);
17626 ma_uint32 marginSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
17630 ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
17646 resultJACK = ((ma_jack_activate_proc)pContext->jack.jack_activate)((ma_jack_client_t*)pDevice->jack.pClient);
17647 if (resultJACK != 0) {
17652 const char** ppServerPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsOutput);
17653 if (ppServerPorts ==
NULL) {
17654 ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17658 for (i = 0; ppServerPorts[i] !=
NULL; ++i) {
17659 const char* pServerPort = ppServerPorts[i];
17660 const char* pClientPort = ((ma_jack_port_name_proc)pContext->jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsCapture[i]);
17662 resultJACK = ((ma_jack_connect_proc)pContext->jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pServerPort, pClientPort);
17663 if (resultJACK != 0) {
17664 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppServerPorts);
17665 ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17670 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppServerPorts);
17674 const char** ppServerPorts = ((ma_jack_get_ports_proc)pContext->jack.jack_get_ports)((ma_jack_client_t*)pDevice->jack.pClient,
NULL,
NULL, ma_JackPortIsPhysical | ma_JackPortIsInput);
17675 if (ppServerPorts ==
NULL) {
17676 ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17680 for (i = 0; ppServerPorts[i] !=
NULL; ++i) {
17681 const char* pServerPort = ppServerPorts[i];
17682 const char* pClientPort = ((ma_jack_port_name_proc)pContext->jack.jack_port_name)((ma_jack_port_t*)pDevice->jack.pPortsPlayback[i]);
17684 resultJACK = ((ma_jack_connect_proc)pContext->jack.jack_connect)((ma_jack_client_t*)pDevice->jack.pClient, pClientPort, pServerPort);
17685 if (resultJACK != 0) {
17686 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppServerPorts);
17687 ((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient);
17692 ((ma_jack_free_proc)pContext->jack.jack_free)((
void*)ppServerPorts);
17703 if (((ma_jack_deactivate_proc)pContext->jack.jack_deactivate)((ma_jack_client_t*)pDevice->jack.pClient) != 0) {
17707 onStop = pDevice->onStop;
17718 ma_assert(pContext !=
NULL);
17721 ma_free(pContext->jack.pClientName);
17722 pContext->jack.pClientName =
NULL;
17724 #ifndef MA_NO_RUNTIME_LINKING
17725 ma_dlclose(pContext, pContext->jack.jackSO);
17733 #ifndef MA_NO_RUNTIME_LINKING
17734 const char* libjackNames[] = {
17744 for (i = 0; i < ma_countof(libjackNames); ++i) {
17745 pContext->jack.jackSO = ma_dlopen(pContext, libjackNames[i]);
17746 if (pContext->jack.jackSO !=
NULL) {
17751 if (pContext->jack.jackSO ==
NULL) {
17755 pContext->jack.jack_client_open = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_client_open");
17756 pContext->jack.jack_client_close = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_client_close");
17757 pContext->jack.jack_client_name_size = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_client_name_size");
17758 pContext->jack.jack_set_process_callback = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_set_process_callback");
17759 pContext->jack.jack_set_buffer_size_callback = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_set_buffer_size_callback");
17760 pContext->jack.jack_on_shutdown = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_on_shutdown");
17761 pContext->jack.jack_get_sample_rate = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_get_sample_rate");
17762 pContext->jack.jack_get_buffer_size = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_get_buffer_size");
17763 pContext->jack.jack_get_ports = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_get_ports");
17764 pContext->jack.jack_activate = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_activate");
17765 pContext->jack.jack_deactivate = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_deactivate");
17766 pContext->jack.jack_connect = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_connect");
17767 pContext->jack.jack_port_register = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_port_register");
17768 pContext->jack.jack_port_name = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_port_name");
17769 pContext->jack.jack_port_get_buffer = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_port_get_buffer");
17770 pContext->jack.jack_free = (
ma_proc)ma_dlsym(pContext, pContext->jack.jackSO,
"jack_free");
17776 ma_jack_client_open_proc _jack_client_open = jack_client_open;
17777 ma_jack_client_close_proc _jack_client_close = jack_client_close;
17778 ma_jack_client_name_size_proc _jack_client_name_size = jack_client_name_size;
17779 ma_jack_set_process_callback_proc _jack_set_process_callback = jack_set_process_callback;
17780 ma_jack_set_buffer_size_callback_proc _jack_set_buffer_size_callback = jack_set_buffer_size_callback;
17781 ma_jack_on_shutdown_proc _jack_on_shutdown = jack_on_shutdown;
17782 ma_jack_get_sample_rate_proc _jack_get_sample_rate = jack_get_sample_rate;
17783 ma_jack_get_buffer_size_proc _jack_get_buffer_size = jack_get_buffer_size;
17784 ma_jack_get_ports_proc _jack_get_ports = jack_get_ports;
17785 ma_jack_activate_proc _jack_activate = jack_activate;
17786 ma_jack_deactivate_proc _jack_deactivate = jack_deactivate;
17787 ma_jack_connect_proc _jack_connect = jack_connect;
17788 ma_jack_port_register_proc _jack_port_register = jack_port_register;
17789 ma_jack_port_name_proc _jack_port_name = jack_port_name;
17790 ma_jack_port_get_buffer_proc _jack_port_get_buffer = jack_port_get_buffer;
17791 ma_jack_free_proc _jack_free = jack_free;
17793 pContext->jack.jack_client_open = (
ma_proc)_jack_client_open;
17794 pContext->jack.jack_client_close = (
ma_proc)_jack_client_close;
17795 pContext->jack.jack_client_name_size = (
ma_proc)_jack_client_name_size;
17796 pContext->jack.jack_set_process_callback = (
ma_proc)_jack_set_process_callback;
17797 pContext->jack.jack_set_buffer_size_callback = (
ma_proc)_jack_set_buffer_size_callback;
17798 pContext->jack.jack_on_shutdown = (
ma_proc)_jack_on_shutdown;
17799 pContext->jack.jack_get_sample_rate = (
ma_proc)_jack_get_sample_rate;
17800 pContext->jack.jack_get_buffer_size = (
ma_proc)_jack_get_buffer_size;
17801 pContext->jack.jack_get_ports = (
ma_proc)_jack_get_ports;
17802 pContext->jack.jack_activate = (
ma_proc)_jack_activate;
17803 pContext->jack.jack_deactivate = (
ma_proc)_jack_deactivate;
17804 pContext->jack.jack_connect = (
ma_proc)_jack_connect;
17805 pContext->jack.jack_port_register = (
ma_proc)_jack_port_register;
17806 pContext->jack.jack_port_name = (
ma_proc)_jack_port_name;
17807 pContext->jack.jack_port_get_buffer = (
ma_proc)_jack_port_get_buffer;
17808 pContext->jack.jack_free = (
ma_proc)_jack_free;
17813 pContext->
onUninit = ma_context_uninit__jack;
17815 pContext->
onEnumDevices = ma_context_enumerate_devices__jack;
17823 pContext->jack.pClientName = ma_copy_string(pConfig->
jack.
pClientName);
17832 ma_jack_client_t* pDummyClient;
17833 ma_result result = ma_context_open_client__jack(pContext, &pDummyClient);
17835 ma_free(pContext->jack.pClientName);
17836 #ifndef MA_NO_RUNTIME_LINKING
17837 ma_dlclose(pContext, pContext->jack.jackSO);
17842 ((ma_jack_client_close_proc)pContext->jack.jack_client_close)((ma_jack_client_t*)pDummyClient);
17856 #ifdef MA_HAS_COREAUDIO
17857 #include <TargetConditionals.h>
17859 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1
17860 #define MA_APPLE_MOBILE
17862 #define MA_APPLE_DESKTOP
17865 #if defined(MA_APPLE_DESKTOP)
17866 #include <CoreAudio/CoreAudio.h>
17868 #include <AVFoundation/AVFoundation.h>
17871 #include <AudioToolbox/AudioToolbox.h>
17874 typedef Boolean (* ma_CFStringGetCString_proc)(CFStringRef theString,
char*
buffer, CFIndex bufferSize, CFStringEncoding encoding);
17875 typedef void (* ma_CFRelease_proc)(CFTypeRef cf);
17878 #if defined(MA_APPLE_DESKTOP)
17879 typedef OSStatus (* ma_AudioObjectGetPropertyData_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* ioDataSize,
void* outData);
17880 typedef OSStatus (* ma_AudioObjectGetPropertyDataSize_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32* outDataSize);
17881 typedef OSStatus (* ma_AudioObjectSetPropertyData_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize,
const void* inQualifierData, UInt32 inDataSize,
const void* inData);
17882 typedef OSStatus (* ma_AudioObjectAddPropertyListener_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener,
void* inClientData);
17883 typedef OSStatus (* ma_AudioObjectRemovePropertyListener_proc)(AudioObjectID inObjectID,
const AudioObjectPropertyAddress* inAddress, AudioObjectPropertyListenerProc inListener,
void* inClientData);
17887 typedef AudioComponent (* ma_AudioComponentFindNext_proc)(AudioComponent inComponent,
const AudioComponentDescription* inDesc);
17888 typedef OSStatus (* ma_AudioComponentInstanceDispose_proc)(AudioComponentInstance inInstance);
17889 typedef OSStatus (* ma_AudioComponentInstanceNew_proc)(AudioComponent inComponent, AudioComponentInstance* outInstance);
17890 typedef OSStatus (* ma_AudioOutputUnitStart_proc)(AudioUnit inUnit);
17891 typedef OSStatus (* ma_AudioOutputUnitStop_proc)(AudioUnit inUnit);
17892 typedef OSStatus (* ma_AudioUnitAddPropertyListener_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc,
void* inProcUserData);
17893 typedef OSStatus (* ma_AudioUnitGetPropertyInfo_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, UInt32* outDataSize, Boolean* outWriteable);
17894 typedef OSStatus (* ma_AudioUnitGetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
void* outData, UInt32* ioDataSize);
17895 typedef OSStatus (* ma_AudioUnitSetProperty_proc)(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement,
const void* inData, UInt32 inDataSize);
17896 typedef OSStatus (* ma_AudioUnitInitialize_proc)(AudioUnit inUnit);
17897 typedef OSStatus (* ma_AudioUnitRender_proc)(AudioUnit inUnit, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData);
17900 #define MA_COREAUDIO_OUTPUT_BUS 0
17901 #define MA_COREAUDIO_INPUT_BUS 1
17938 ma_result ma_result_from_OSStatus(OSStatus status)
17943 #if defined(MA_APPLE_DESKTOP)
17945 case kAudioHardwareUnspecifiedError:
return MA_ERROR;
17961 ma_channel ma_channel_from_AudioChannelBitmap(AudioChannelBitmap bit)
17988 ma_channel ma_channel_from_AudioChannelLabel(AudioChannelLabel
label)
18082 ma_result ma_format_from_AudioStreamBasicDescription(
const AudioStreamBasicDescription* pDescription,
ma_format* pFormatOut)
18084 ma_assert(pDescription !=
NULL);
18085 ma_assert(pFormatOut !=
NULL);
18090 if (pDescription->mFormatID != kAudioFormatLinearPCM) {
18095 if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) != 0) {
18100 if ((ma_is_little_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) != 0) || (ma_is_big_endian() && (pDescription->mFormatFlags & kAudioFormatFlagIsBigEndian) == 0)) {
18109 if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0) {
18110 if (pDescription->mBitsPerChannel == 32) {
18115 if ((pDescription->mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) != 0) {
18116 if (pDescription->mBitsPerChannel == 16) {
18119 }
else if (pDescription->mBitsPerChannel == 24) {
18120 if (pDescription->mBytesPerFrame == (pDescription->mBitsPerChannel/8 * pDescription->mChannelsPerFrame)) {
18124 if (pDescription->mBytesPerFrame/pDescription->mChannelsPerFrame ==
sizeof(
ma_int32)) {
18131 }
else if (pDescription->mBitsPerChannel == 32) {
18136 if (pDescription->mBitsPerChannel == 8) {
18149 ma_assert(pChannelLayout !=
NULL);
18151 if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
18153 for (iChannel = 0; iChannel < pChannelLayout->mNumberChannelDescriptions; ++iChannel) {
18154 channelMap[iChannel] = ma_channel_from_AudioChannelLabel(pChannelLayout->mChannelDescriptions[iChannel].mChannelLabel);
18158 if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
18160 UInt32 iChannel = 0;
18162 AudioChannelBitmap bitmap = pChannelLayout->mChannelBitmap;
18163 for (iBit = 0; iBit < 32; ++iBit) {
18164 AudioChannelBitmap bit = bitmap & (1 << iBit);
18166 channelMap[iChannel++] = ma_channel_from_AudioChannelBit(bit);
18176 UInt32 channelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
18177 switch (pChannelLayout->mChannelLayoutTag)
18179 case kAudioChannelLayoutTag_Mono:
18180 case kAudioChannelLayoutTag_Stereo:
18181 case kAudioChannelLayoutTag_StereoHeadphones:
18182 case kAudioChannelLayoutTag_MatrixStereo:
18183 case kAudioChannelLayoutTag_MidSide:
18184 case kAudioChannelLayoutTag_XY:
18185 case kAudioChannelLayoutTag_Binaural:
18186 case kAudioChannelLayoutTag_Ambisonic_B_Format:
18191 case kAudioChannelLayoutTag_Octagonal:
18196 case kAudioChannelLayoutTag_Hexagonal:
18200 case kAudioChannelLayoutTag_Pentagonal:
18204 case kAudioChannelLayoutTag_Quadraphonic:
18225 #if defined(MA_APPLE_DESKTOP)
18226 ma_result ma_get_device_object_ids__coreaudio(
ma_context* pContext, UInt32* pDeviceCount, AudioObjectID** ppDeviceObjectIDs)
18228 AudioObjectPropertyAddress propAddressDevices;
18229 UInt32 deviceObjectsDataSize;
18231 AudioObjectID* pDeviceObjectIDs;
18233 ma_assert(pContext !=
NULL);
18234 ma_assert(pDeviceCount !=
NULL);
18235 ma_assert(ppDeviceObjectIDs !=
NULL);
18239 *ppDeviceObjectIDs =
NULL;
18241 propAddressDevices.mSelector = kAudioHardwarePropertyDevices;
18242 propAddressDevices.mScope = kAudioObjectPropertyScopeGlobal;
18243 propAddressDevices.mElement = kAudioObjectPropertyElementMaster;
18245 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(kAudioObjectSystemObject, &propAddressDevices, 0,
NULL, &deviceObjectsDataSize);
18246 if (status != noErr) {
18247 return ma_result_from_OSStatus(status);
18250 pDeviceObjectIDs = (AudioObjectID*)
ma_malloc(deviceObjectsDataSize);
18251 if (pDeviceObjectIDs ==
NULL) {
18255 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDevices, 0,
NULL, &deviceObjectsDataSize, pDeviceObjectIDs);
18256 if (status != noErr) {
18258 return ma_result_from_OSStatus(status);
18261 *pDeviceCount = deviceObjectsDataSize /
sizeof(AudioObjectID);
18262 *ppDeviceObjectIDs = pDeviceObjectIDs;
18268 ma_result ma_get_AudioObject_uid_as_CFStringRef(
ma_context* pContext, AudioObjectID objectID, CFStringRef* pUID)
18270 AudioObjectPropertyAddress propAddress;
18274 ma_assert(pContext !=
NULL);
18276 propAddress.mSelector = kAudioDevicePropertyDeviceUID;
18277 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
18278 propAddress.mElement = kAudioObjectPropertyElementMaster;
18281 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0,
NULL, &
dataSize, pUID);
18282 if (status != noErr) {
18283 return ma_result_from_OSStatus(status);
18289 ma_result ma_get_AudioObject_uid(
ma_context* pContext, AudioObjectID objectID,
size_t bufferSize,
char* bufferOut)
18294 ma_assert(pContext !=
NULL);
18296 result = ma_get_AudioObject_uid_as_CFStringRef(pContext, objectID, &uid);
18301 if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(uid, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
18305 ((ma_CFRelease_proc)pContext->coreaudio.CFRelease)(uid);
18309 ma_result ma_get_AudioObject_name(
ma_context* pContext, AudioObjectID objectID,
size_t bufferSize,
char* bufferOut)
18311 AudioObjectPropertyAddress propAddress;
18312 CFStringRef deviceName =
NULL;
18316 ma_assert(pContext !=
NULL);
18318 propAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
18319 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
18320 propAddress.mElement = kAudioObjectPropertyElementMaster;
18323 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(objectID, &propAddress, 0,
NULL, &
dataSize, &deviceName);
18324 if (status != noErr) {
18325 return ma_result_from_OSStatus(status);
18328 if (!((ma_CFStringGetCString_proc)pContext->coreaudio.CFStringGetCString)(deviceName, bufferOut, bufferSize, kCFStringEncodingUTF8)) {
18332 ((ma_CFRelease_proc)pContext->coreaudio.CFRelease)(deviceName);
18336 ma_bool32 ma_does_AudioObject_support_scope(
ma_context* pContext, AudioObjectID deviceObjectID, AudioObjectPropertyScope scope)
18338 AudioObjectPropertyAddress propAddress;
18341 AudioBufferList* pBufferList;
18344 ma_assert(pContext !=
NULL);
18347 propAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
18348 propAddress.mScope = scope;
18349 propAddress.mElement = kAudioObjectPropertyElementMaster;
18351 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize);
18352 if (status != noErr) {
18357 if (pBufferList ==
NULL) {
18361 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize, pBufferList);
18362 if (status != noErr) {
18368 if (pBufferList->mNumberBuffers > 0) {
18373 return isSupported;
18376 ma_bool32 ma_does_AudioObject_support_playback(
ma_context* pContext, AudioObjectID deviceObjectID)
18378 return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeOutput);
18381 ma_bool32 ma_does_AudioObject_support_capture(
ma_context* pContext, AudioObjectID deviceObjectID)
18383 return ma_does_AudioObject_support_scope(pContext, deviceObjectID, kAudioObjectPropertyScopeInput);
18387 ma_result ma_get_AudioObject_stream_descriptions(
ma_context* pContext, AudioObjectID deviceObjectID,
ma_device_type deviceType, UInt32* pDescriptionCount, AudioStreamRangedDescription** ppDescriptions)
18389 AudioObjectPropertyAddress propAddress;
18392 AudioStreamRangedDescription* pDescriptions;
18394 ma_assert(pContext !=
NULL);
18395 ma_assert(pDescriptionCount !=
NULL);
18396 ma_assert(ppDescriptions !=
NULL);
18402 propAddress.mSelector = kAudioStreamPropertyAvailableVirtualFormats;
18403 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18404 propAddress.mElement = kAudioObjectPropertyElementMaster;
18406 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize);
18407 if (status != noErr) {
18408 return ma_result_from_OSStatus(status);
18412 if (pDescriptions ==
NULL) {
18416 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize, pDescriptions);
18417 if (status != noErr) {
18419 return ma_result_from_OSStatus(status);
18422 *pDescriptionCount =
dataSize /
sizeof(*pDescriptions);
18423 *ppDescriptions = pDescriptions;
18428 ma_result ma_get_AudioObject_channel_layout(
ma_context* pContext, AudioObjectID deviceObjectID,
ma_device_type deviceType, AudioChannelLayout** ppChannelLayout)
18430 AudioObjectPropertyAddress propAddress;
18433 AudioChannelLayout* pChannelLayout;
18435 ma_assert(pContext !=
NULL);
18436 ma_assert(ppChannelLayout !=
NULL);
18438 *ppChannelLayout =
NULL;
18440 propAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout;
18441 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18442 propAddress.mElement = kAudioObjectPropertyElementMaster;
18444 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize);
18445 if (status != noErr) {
18446 return ma_result_from_OSStatus(status);
18450 if (pChannelLayout ==
NULL) {
18454 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize, pChannelLayout);
18455 if (status != noErr) {
18457 return ma_result_from_OSStatus(status);
18460 *ppChannelLayout = pChannelLayout;
18466 AudioChannelLayout* pChannelLayout;
18469 ma_assert(pContext !=
NULL);
18470 ma_assert(pChannelCount !=
NULL);
18472 *pChannelCount = 0;
18474 result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
18479 if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
18480 *pChannelCount = pChannelLayout->mNumberChannelDescriptions;
18481 }
else if (pChannelLayout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
18482 *pChannelCount = ma_count_set_bits(pChannelLayout->mChannelBitmap);
18484 *pChannelCount = AudioChannelLayoutTag_GetNumberOfChannels(pChannelLayout->mChannelLayoutTag);
18493 AudioChannelLayout* pChannelLayout;
18496 ma_assert(pContext !=
NULL);
18498 result = ma_get_AudioObject_channel_layout(pContext, deviceObjectID, deviceType, &pChannelLayout);
18503 result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, channelMap);
18513 ma_result ma_get_AudioObject_sample_rates(
ma_context* pContext, AudioObjectID deviceObjectID,
ma_device_type deviceType, UInt32* pSampleRateRangesCount, AudioValueRange** ppSampleRateRanges)
18515 AudioObjectPropertyAddress propAddress;
18518 AudioValueRange* pSampleRateRanges;
18520 ma_assert(pContext !=
NULL);
18521 ma_assert(pSampleRateRangesCount !=
NULL);
18522 ma_assert(ppSampleRateRanges !=
NULL);
18525 *pSampleRateRangesCount = 0;
18526 *ppSampleRateRanges =
NULL;
18528 propAddress.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
18529 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18530 propAddress.mElement = kAudioObjectPropertyElementMaster;
18532 status = ((ma_AudioObjectGetPropertyDataSize_proc)pContext->coreaudio.AudioObjectGetPropertyDataSize)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize);
18533 if (status != noErr) {
18534 return ma_result_from_OSStatus(status);
18538 if (pSampleRateRanges ==
NULL) {
18542 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize, pSampleRateRanges);
18543 if (status != noErr) {
18545 return ma_result_from_OSStatus(status);
18548 *pSampleRateRangesCount =
dataSize /
sizeof(*pSampleRateRanges);
18549 *ppSampleRateRanges = pSampleRateRanges;
18555 UInt32 sampleRateRangeCount;
18556 AudioValueRange* pSampleRateRanges;
18559 ma_assert(pContext !=
NULL);
18560 ma_assert(pSampleRateOut !=
NULL);
18562 *pSampleRateOut = 0;
18564 result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
18569 if (sampleRateRangeCount == 0) {
18574 if (sampleRateIn == 0) {
18576 UInt32 iMALSampleRate;
18577 for (iMALSampleRate = 0; iMALSampleRate < ma_countof(g_maStandardSampleRatePriorities); ++iMALSampleRate) {
18578 ma_uint32 malSampleRate = g_maStandardSampleRatePriorities[iMALSampleRate];
18579 UInt32 iCASampleRate;
18580 for (iCASampleRate = 0; iCASampleRate < sampleRateRangeCount; ++iCASampleRate) {
18581 AudioValueRange caSampleRate = pSampleRateRanges[iCASampleRate];
18582 if (caSampleRate.mMinimum <= malSampleRate && caSampleRate.mMaximum >= malSampleRate) {
18583 *pSampleRateOut = malSampleRate;
18594 ma_assert(sampleRateRangeCount > 0);
18596 *pSampleRateOut = pSampleRateRanges[0].mMinimum;
18601 UInt32 currentAbsoluteDifference =
INT32_MAX;
18602 UInt32 iCurrentClosestRange = (UInt32)-1;
18604 for (iRange = 0; iRange < sampleRateRangeCount; ++iRange) {
18605 if (pSampleRateRanges[iRange].mMinimum <= sampleRateIn && pSampleRateRanges[iRange].mMaximum >= sampleRateIn) {
18606 *pSampleRateOut = sampleRateIn;
18610 UInt32 absoluteDifference;
18611 if (pSampleRateRanges[iRange].mMinimum > sampleRateIn) {
18612 absoluteDifference = pSampleRateRanges[iRange].mMinimum - sampleRateIn;
18614 absoluteDifference = sampleRateIn - pSampleRateRanges[iRange].mMaximum;
18617 if (currentAbsoluteDifference > absoluteDifference) {
18618 currentAbsoluteDifference = absoluteDifference;
18619 iCurrentClosestRange = iRange;
18624 ma_assert(iCurrentClosestRange != (UInt32)-1);
18626 *pSampleRateOut = pSampleRateRanges[iCurrentClosestRange].mMinimum;
18639 AudioObjectPropertyAddress propAddress;
18640 AudioValueRange bufferSizeRange;
18644 ma_assert(pContext !=
NULL);
18645 ma_assert(pBufferSizeInFramesOut !=
NULL);
18647 *pBufferSizeInFramesOut = 0;
18649 propAddress.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
18650 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18651 propAddress.mElement = kAudioObjectPropertyElementMaster;
18653 dataSize =
sizeof(bufferSizeRange);
18654 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize, &bufferSizeRange);
18655 if (status != noErr) {
18656 return ma_result_from_OSStatus(status);
18660 if (bufferSizeInFramesIn < bufferSizeRange.mMinimum) {
18661 *pBufferSizeInFramesOut = (
ma_uint32)bufferSizeRange.mMinimum;
18662 }
else if (bufferSizeInFramesIn > bufferSizeRange.mMaximum) {
18663 *pBufferSizeInFramesOut = (
ma_uint32)bufferSizeRange.mMaximum;
18665 *pBufferSizeInFramesOut = bufferSizeInFramesIn;
18675 AudioObjectPropertyAddress propAddress;
18679 ma_assert(pContext !=
NULL);
18681 result = ma_get_AudioObject_closest_buffer_size_in_frames(pContext, deviceObjectID, deviceType, *pBufferSizeInOut, &chosenBufferSizeInFrames);
18687 propAddress.mSelector = kAudioDevicePropertyBufferFrameSize;
18688 propAddress.mScope = (deviceType ==
ma_device_type_playback) ? kAudioObjectPropertyScopeOutput : kAudioObjectPropertyScopeInput;
18689 propAddress.mElement = kAudioObjectPropertyElementMaster;
18691 ((ma_AudioObjectSetPropertyData_proc)pContext->coreaudio.AudioObjectSetPropertyData)(deviceObjectID, &propAddress, 0,
NULL,
sizeof(chosenBufferSizeInFrames), &chosenBufferSizeInFrames);
18694 dataSize =
sizeof(*pBufferSizeInOut);
18695 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(deviceObjectID, &propAddress, 0,
NULL, &
dataSize, &chosenBufferSizeInFrames);
18696 if (status != noErr) {
18697 return ma_result_from_OSStatus(status);
18700 *pBufferSizeInOut = chosenBufferSizeInFrames;
18707 ma_assert(pContext !=
NULL);
18708 ma_assert(pDeviceObjectID !=
NULL);
18711 *pDeviceObjectID = 0;
18713 if (pDeviceID ==
NULL) {
18715 AudioObjectPropertyAddress propAddressDefaultDevice;
18716 UInt32 defaultDeviceObjectIDSize =
sizeof(AudioObjectID);
18717 AudioObjectID defaultDeviceObjectID;
18720 propAddressDefaultDevice.mScope = kAudioObjectPropertyScopeGlobal;
18721 propAddressDefaultDevice.mElement = kAudioObjectPropertyElementMaster;
18723 propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
18725 propAddressDefaultDevice.mSelector = kAudioHardwarePropertyDefaultInputDevice;
18728 defaultDeviceObjectIDSize =
sizeof(AudioObjectID);
18729 status = ((ma_AudioObjectGetPropertyData_proc)pContext->coreaudio.AudioObjectGetPropertyData)(kAudioObjectSystemObject, &propAddressDefaultDevice, 0,
NULL, &defaultDeviceObjectIDSize, &defaultDeviceObjectID);
18730 if (status == noErr) {
18731 *pDeviceObjectID = defaultDeviceObjectID;
18736 UInt32 deviceCount;
18737 AudioObjectID* pDeviceObjectIDs;
18741 result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
18746 for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
18747 AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
18750 if (ma_get_AudioObject_uid(pContext, deviceObjectID,
sizeof(uid), uid) !=
MA_SUCCESS) {
18755 if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
18756 if (strcmp(uid, pDeviceID->coreaudio) == 0) {
18757 *pDeviceObjectID = deviceObjectID;
18763 if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
18764 if (strcmp(uid, pDeviceID->coreaudio) == 0) {
18765 *pDeviceObjectID = deviceObjectID;
18783 UInt32 deviceFormatDescriptionCount;
18784 AudioStreamRangedDescription* pDeviceFormatDescriptions;
18789 AudioStreamBasicDescription bestDeviceFormatSoFar;
18793 result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &deviceFormatDescriptionCount, &pDeviceFormatDescriptions);
18798 desiredSampleRate = sampleRate;
18799 if (usingDefaultSampleRate) {
18805 for (iStandardRate = 0; iStandardRate < ma_countof(g_maStandardSampleRatePriorities); ++iStandardRate) {
18806 ma_uint32 standardRate = g_maStandardSampleRatePriorities[iStandardRate];
18808 UInt32 iDeviceRate;
18810 for (iDeviceRate = 0; iDeviceRate < deviceFormatDescriptionCount; ++iDeviceRate) {
18811 ma_uint32 deviceRate = (
ma_uint32)pDeviceFormatDescriptions[iDeviceRate].mFormat.mSampleRate;
18813 if (deviceRate == standardRate) {
18814 desiredSampleRate = standardRate;
18826 desiredChannelCount = channels;
18827 if (usingDefaultChannels) {
18828 ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &desiredChannelCount);
18832 if (usingDefaultFormat) {
18833 desiredFormat = g_maFormatPriorities[0];
18840 ma_zero_object(&bestDeviceFormatSoFar);
18843 for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
18845 ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &
format);
18847 hasSupportedFormat =
MA_TRUE;
18848 bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat;
18853 if (!hasSupportedFormat) {
18854 ma_free(pDeviceFormatDescriptions);
18859 for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) {
18860 AudioStreamBasicDescription thisDeviceFormat = pDeviceFormatDescriptions[iFormat].mFormat;
18866 formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &thisSampleFormat);
18871 ma_format_from_AudioStreamBasicDescription(&bestDeviceFormatSoFar, &bestSampleFormatSoFar);
18874 if (thisDeviceFormat.mSampleRate != desiredSampleRate) {
18879 if (bestDeviceFormatSoFar.mSampleRate == desiredSampleRate) {
18883 if (thisDeviceFormat.mChannelsPerFrame != desiredChannelCount) {
18885 if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
18892 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
18893 bestDeviceFormatSoFar = thisDeviceFormat;
18901 if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
18903 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
18904 bestDeviceFormatSoFar = thisDeviceFormat;
18911 bestDeviceFormatSoFar = thisDeviceFormat;
18921 if (bestDeviceFormatSoFar.mSampleRate != desiredSampleRate) {
18922 bestDeviceFormatSoFar = thisDeviceFormat;
18926 if (thisDeviceFormat.mChannelsPerFrame == desiredChannelCount) {
18931 if (bestDeviceFormatSoFar.mChannelsPerFrame != desiredChannelCount) {
18932 bestDeviceFormatSoFar = thisDeviceFormat;
18936 if (thisSampleFormat == desiredFormat) {
18937 bestDeviceFormatSoFar = thisDeviceFormat;
18941 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
18942 bestDeviceFormatSoFar = thisDeviceFormat;
18954 if (bestDeviceFormatSoFar.mChannelsPerFrame == desiredChannelCount) {
18961 if (thisSampleFormat == bestSampleFormatSoFar) {
18962 if (ma_get_format_priority_index(thisSampleFormat) < ma_get_format_priority_index(bestSampleFormatSoFar)) {
18963 bestDeviceFormatSoFar = thisDeviceFormat;
18975 *pFormat = bestDeviceFormatSoFar;
18977 ma_free(pDeviceFormatDescriptions);
18984 AudioUnitScope deviceScope;
18985 AudioUnitElement deviceBus;
18986 UInt32 channelLayoutSize;
18988 AudioChannelLayout* pChannelLayout;
18991 ma_assert(pContext !=
NULL);
18994 deviceScope = kAudioUnitScope_Output;
18995 deviceBus = MA_COREAUDIO_OUTPUT_BUS;
18997 deviceScope = kAudioUnitScope_Input;
18998 deviceBus = MA_COREAUDIO_INPUT_BUS;
19001 status = ((ma_AudioUnitGetPropertyInfo_proc)pContext->coreaudio.AudioUnitGetPropertyInfo)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, &channelLayoutSize,
NULL);
19002 if (status != noErr) {
19003 return ma_result_from_OSStatus(status);
19006 pChannelLayout = (AudioChannelLayout*)
ma_malloc(channelLayoutSize);
19007 if (pChannelLayout ==
NULL) {
19011 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_AudioChannelLayout, deviceScope, deviceBus, pChannelLayout, &channelLayoutSize);
19012 if (status != noErr) {
19014 return ma_result_from_OSStatus(status);
19017 result = ma_get_channel_map_from_AudioChannelLayout(pChannelLayout, channelMap);
19029 ma_assert(pContext !=
NULL);
19030 ma_assert(pID0 !=
NULL);
19031 ma_assert(pID1 !=
NULL);
19034 return strcmp(pID0->coreaudio, pID1->coreaudio) == 0;
19039 #if defined(MA_APPLE_DESKTOP)
19040 UInt32 deviceCount;
19041 AudioObjectID* pDeviceObjectIDs;
19045 result = ma_get_device_object_ids__coreaudio(pContext, &deviceCount, &pDeviceObjectIDs);
19050 for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
19051 AudioObjectID deviceObjectID = pDeviceObjectIDs[iDevice];
19054 ma_zero_object(&info);
19055 if (ma_get_AudioObject_uid(pContext, deviceObjectID,
sizeof(info.
id.coreaudio), info.
id.coreaudio) !=
MA_SUCCESS) {
19058 if (ma_get_AudioObject_name(pContext, deviceObjectID,
sizeof(info.
name), info.
name) !=
MA_SUCCESS) {
19062 if (ma_does_AudioObject_support_playback(pContext, deviceObjectID)) {
19067 if (ma_does_AudioObject_support_capture(pContext, deviceObjectID)) {
19079 ma_zero_object(&info);
19080 ma_strncpy_s(info.
name,
sizeof(info.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
19085 ma_zero_object(&info);
19086 ma_strncpy_s(info.
name,
sizeof(info.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
19099 ma_assert(pContext !=
NULL);
19106 #if defined(MA_APPLE_DESKTOP)
19109 AudioObjectID deviceObjectID;
19110 UInt32 streamDescriptionCount;
19111 AudioStreamRangedDescription* pStreamDescriptions;
19112 UInt32 iStreamDescription;
19113 UInt32 sampleRateRangeCount;
19114 AudioValueRange* pSampleRateRanges;
19116 result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
19121 result = ma_get_AudioObject_uid(pContext, deviceObjectID,
sizeof(pDeviceInfo->
id.coreaudio), pDeviceInfo->
id.coreaudio);
19126 result = ma_get_AudioObject_name(pContext, deviceObjectID,
sizeof(pDeviceInfo->
name), pDeviceInfo->
name);
19132 result = ma_get_AudioObject_stream_descriptions(pContext, deviceObjectID, deviceType, &streamDescriptionCount, &pStreamDescriptions);
19137 for (iStreamDescription = 0; iStreamDescription < streamDescriptionCount; ++iStreamDescription) {
19142 result = ma_format_from_AudioStreamBasicDescription(&pStreamDescriptions[iStreamDescription].mFormat, &
format);
19150 for (iOutputFormat = 0; iOutputFormat < pDeviceInfo->
formatCount; ++iOutputFormat) {
19157 if (!formatExists) {
19162 ma_free(pStreamDescriptions);
19166 result = ma_get_AudioObject_channel_count(pContext, deviceObjectID, deviceType, &pDeviceInfo->
minChannels);
19174 result = ma_get_AudioObject_sample_rates(pContext, deviceObjectID, deviceType, &sampleRateRangeCount, &pSampleRateRanges);
19179 if (sampleRateRangeCount > 0) {
19180 UInt32 iSampleRate;
19183 for (iSampleRate = 0; iSampleRate < sampleRateRangeCount; ++iSampleRate) {
19184 if (pDeviceInfo->
minSampleRate > pSampleRateRanges[iSampleRate].mMinimum) {
19185 pDeviceInfo->
minSampleRate = pSampleRateRanges[iSampleRate].mMinimum;
19187 if (pDeviceInfo->
maxSampleRate < pSampleRateRanges[iSampleRate].mMaximum) {
19188 pDeviceInfo->
maxSampleRate = pSampleRateRanges[iSampleRate].mMaximum;
19196 AudioComponentDescription desc;
19197 AudioComponent component;
19198 AudioUnit audioUnit;
19200 AudioUnitScope formatScope;
19201 AudioUnitElement formatElement;
19202 AudioStreamBasicDescription bestFormat;
19206 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
19208 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
19216 desc.componentType = kAudioUnitType_Output;
19217 desc.componentSubType = kAudioUnitSubType_RemoteIO;
19218 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
19219 desc.componentFlags = 0;
19220 desc.componentFlagsMask = 0;
19222 component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(
NULL, &desc);
19223 if (component ==
NULL) {
19227 status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)(component, &audioUnit);
19228 if (status != noErr) {
19229 return ma_result_from_OSStatus(status);
19235 propSize =
sizeof(bestFormat);
19236 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
19237 if (status != noErr) {
19238 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
19239 return ma_result_from_OSStatus(status);
19242 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(audioUnit);
19246 pDeviceInfo->
minChannels = bestFormat.mChannelsPerFrame;
19247 pDeviceInfo->
maxChannels = bestFormat.mChannelsPerFrame;
19250 result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pDeviceInfo->
formats[0]);
19260 AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
19261 ma_assert(pAudioSession !=
NULL);
19274 OSStatus ma_on_output__coreaudio(
void* pUserData, AudioUnitRenderActionFlags* pActionFlags,
const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufferList)
19279 ma_assert(pDevice !=
NULL);
19281 #if defined(MA_DEBUG_OUTPUT)
19282 printf(
"INFO: Output Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pBufferList->mNumberBuffers);
19287 if (pBufferList->mBuffers[0].mNumberChannels != pDevice->playback.internalChannels) {
19294 for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
19295 if (pBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->playback.internalChannels) {
19296 ma_uint32 frameCountForThisBuffer = pBufferList->mBuffers[iBuffer].mDataByteSize / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
19297 if (frameCountForThisBuffer > 0) {
19299 ma_device__handle_duplex_callback_playback(pDevice, frameCountForThisBuffer, pBufferList->mBuffers[iBuffer].mData, &pDevice->coreaudio.duplexRB);
19301 ma_device__read_frames_from_client(pDevice, frameCountForThisBuffer, pBufferList->mBuffers[iBuffer].mData);
19305 #if defined(MA_DEBUG_OUTPUT)
19306 printf(
" frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pBufferList->mBuffers[iBuffer].mNumberChannels, pBufferList->mBuffers[iBuffer].mDataByteSize);
19314 ma_zero_memory(pBufferList->mBuffers[iBuffer].mData, pBufferList->mBuffers[iBuffer].mDataByteSize);
19316 #if defined(MA_DEBUG_OUTPUT)
19317 printf(
" WARNING: Outputting silence. frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pBufferList->mBuffers[iBuffer].mNumberChannels, pBufferList->mBuffers[iBuffer].mDataByteSize);
19325 for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; iBuffer += pDevice->playback.internalChannels) {
19327 ma_uint32 framesRemaining = frameCountPerBuffer;
19329 while (framesRemaining > 0) {
19332 ma_uint32 framesToRead =
sizeof(tempBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
19333 if (framesToRead > framesRemaining) {
19334 framesToRead = framesRemaining;
19338 ma_device__handle_duplex_callback_playback(pDevice, framesToRead, tempBuffer, &pDevice->coreaudio.duplexRB);
19340 ma_device__read_frames_from_client(pDevice, framesToRead, tempBuffer);
19343 for (iChannel = 0; iChannel < pDevice->playback.internalChannels; ++iChannel) {
19344 ppDeinterleavedBuffers[iChannel] = (
void*)ma_offset_ptr(pBufferList->mBuffers[iBuffer].mData, (frameCountPerBuffer - framesRemaining) *
ma_get_bytes_per_sample(pDevice->playback.internalFormat));
19347 ma_deinterleave_pcm_frames(pDevice->playback.internalFormat, pDevice->playback.internalChannels, framesToRead, tempBuffer, ppDeinterleavedBuffers);
19349 framesRemaining -= framesToRead;
19354 (
void)pActionFlags;
19361 OSStatus ma_on_input__coreaudio(
void* pUserData, AudioUnitRenderActionFlags* pActionFlags,
const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pUnusedBufferList)
19364 AudioBufferList* pRenderedBufferList;
19368 ma_assert(pDevice !=
NULL);
19370 pRenderedBufferList = (AudioBufferList*)pDevice->coreaudio.pAudioBufferList;
19371 ma_assert(pRenderedBufferList);
19375 if (pRenderedBufferList->mBuffers[0].mNumberChannels != pDevice->capture.internalChannels) {
19379 #if defined(MA_DEBUG_OUTPUT)
19380 printf(
"INFO: Input Callback: busNumber=%d, frameCount=%d, mNumberBuffers=%d\n", busNumber, frameCount, pRenderedBufferList->mNumberBuffers);
19383 status = ((ma_AudioUnitRender_proc)pDevice->pContext->coreaudio.AudioUnitRender)((AudioUnit)pDevice->coreaudio.audioUnitCapture, pActionFlags, pTimeStamp, busNumber, frameCount, pRenderedBufferList);
19384 if (status != noErr) {
19385 #if defined(MA_DEBUG_OUTPUT)
19386 printf(
" ERROR: AudioUnitRender() failed with %d\n", status);
19393 for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; ++iBuffer) {
19394 if (pRenderedBufferList->mBuffers[iBuffer].mNumberChannels == pDevice->capture.internalChannels) {
19396 ma_device__handle_duplex_callback_capture(pDevice, frameCount, pRenderedBufferList->mBuffers[iBuffer].mData, &pDevice->coreaudio.duplexRB);
19398 ma_device__send_frames_to_client(pDevice, frameCount, pRenderedBufferList->mBuffers[iBuffer].mData);
19400 #if defined(MA_DEBUG_OUTPUT)
19401 printf(
" mDataByteSize=%d\n", pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
19411 ma_zero_memory(silentBuffer,
sizeof(silentBuffer));
19413 framesRemaining = frameCount;
19414 while (framesRemaining > 0) {
19415 ma_uint32 framesToSend =
sizeof(silentBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
19416 if (framesToSend > framesRemaining) {
19417 framesToSend = framesRemaining;
19421 ma_device__handle_duplex_callback_capture(pDevice, framesToSend, silentBuffer, &pDevice->coreaudio.duplexRB);
19423 ma_device__send_frames_to_client(pDevice, framesToSend, silentBuffer);
19426 framesRemaining -= framesToSend;
19429 #if defined(MA_DEBUG_OUTPUT)
19430 printf(
" WARNING: Outputting silence. frameCount=%d, mNumberChannels=%d, mDataByteSize=%d\n", frameCount, pRenderedBufferList->mBuffers[iBuffer].mNumberChannels, pRenderedBufferList->mBuffers[iBuffer].mDataByteSize);
19438 for (iBuffer = 0; iBuffer < pRenderedBufferList->mNumberBuffers; iBuffer += pDevice->capture.internalChannels) {
19439 ma_uint32 framesRemaining = frameCount;
19440 while (framesRemaining > 0) {
19444 if (framesToSend > framesRemaining) {
19445 framesToSend = framesRemaining;
19448 for (iChannel = 0; iChannel < pDevice->capture.internalChannels; ++iChannel) {
19449 ppDeinterleavedBuffers[iChannel] = (
void*)ma_offset_ptr(pRenderedBufferList->mBuffers[iBuffer].mData, (frameCount - framesRemaining) *
ma_get_bytes_per_sample(pDevice->capture.internalFormat));
19452 ma_interleave_pcm_frames(pDevice->capture.internalFormat, pDevice->capture.internalChannels, framesToSend, (
const void**)ppDeinterleavedBuffers, tempBuffer);
19455 ma_device__handle_duplex_callback_capture(pDevice, framesToSend, tempBuffer, &pDevice->coreaudio.duplexRB);
19457 ma_device__send_frames_to_client(pDevice, framesToSend, tempBuffer);
19460 framesRemaining -= framesToSend;
19465 (
void)pActionFlags;
19469 (
void)pUnusedBufferList;
19474 void on_start_stop__coreaudio(
void* pUserData, AudioUnit audioUnit, AudioUnitPropertyID propertyID, AudioUnitScope scope, AudioUnitElement element)
19477 ma_assert(pDevice !=
NULL);
19485 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED || ma_device__get_state(pDevice) == MA_STATE_STOPPING || ma_device__get_state(pDevice) == MA_STATE_STOPPED) {
19491 ma_event_signal(&pDevice->coreaudio.stopEvent);
19494 UInt32 isRunningSize =
sizeof(isRunning);
19495 OSStatus status = ((ma_AudioUnitGetProperty_proc)pDevice->pContext->coreaudio.AudioUnitGetProperty)(audioUnit, kAudioOutputUnitProperty_IsRunning, scope, element, &isRunning, &isRunningSize);
19496 if (status != noErr) {
19511 if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isDefaultPlaybackDevice) ||
19512 ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isDefaultCaptureDevice)) {
19519 if (((audioUnit == pDevice->coreaudio.audioUnitPlayback) && pDevice->coreaudio.isSwitchingPlaybackDevice) ||
19520 ((audioUnit == pDevice->coreaudio.audioUnitCapture) && pDevice->coreaudio.isSwitchingCaptureDevice)) {
19535 onStop = pDevice->onStop;
19545 #if defined(MA_APPLE_DESKTOP)
19546 static ma_uint32 g_DeviceTrackingInitCounter_CoreAudio = 0;
19547 static ma_mutex g_DeviceTrackingMutex_CoreAudio;
19549 static ma_uint32 g_TrackedDeviceCap_CoreAudio = 0;
19550 static ma_uint32 g_TrackedDeviceCount_CoreAudio = 0;
19552 OSStatus ma_default_device_changed__coreaudio(AudioObjectID objectID, UInt32 addressCount,
const AudioObjectPropertyAddress* pAddresses,
void* pUserData)
19557 if (addressCount == 0) {
19561 if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultOutputDevice) {
19563 }
else if (pAddresses[0].mSelector == kAudioHardwarePropertyDefaultInputDevice) {
19572 for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
19576 pDevice = g_ppTrackedDevices_CoreAudio[iDevice];
19579 pDevice->coreaudio.isSwitchingPlaybackDevice =
MA_TRUE;
19580 reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType,
MA_TRUE);
19581 pDevice->coreaudio.isSwitchingPlaybackDevice =
MA_FALSE;
19583 pDevice->coreaudio.isSwitchingCaptureDevice =
MA_TRUE;
19584 reinitResult = ma_device_reinit_internal__coreaudio(pDevice, deviceType,
MA_TRUE);
19585 pDevice->coreaudio.isSwitchingCaptureDevice =
MA_FALSE;
19589 ma_device__post_init_setup(pDevice, deviceType);
19592 if (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
19595 status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
19596 if (status != noErr) {
19598 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
19600 ma_device__set_state(pDevice, MA_STATE_STOPPED);
19603 status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
19604 if (status != noErr) {
19606 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
19608 ma_device__set_state(pDevice, MA_STATE_STOPPED);
19624 ma_assert(pContext !=
NULL);
19626 if (ma_atomic_increment_32(&g_DeviceTrackingInitCounter_CoreAudio) == 1) {
19627 AudioObjectPropertyAddress propAddress;
19628 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
19629 propAddress.mElement = kAudioObjectPropertyElementMaster;
19633 propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
19634 ((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio,
NULL);
19636 propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
19637 ((ma_AudioObjectAddPropertyListener_proc)pContext->coreaudio.AudioObjectAddPropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio,
NULL);
19645 ma_assert(pContext !=
NULL);
19647 if (ma_atomic_decrement_32(&g_DeviceTrackingInitCounter_CoreAudio) == 0) {
19648 AudioObjectPropertyAddress propAddress;
19649 propAddress.mScope = kAudioObjectPropertyScopeGlobal;
19650 propAddress.mElement = kAudioObjectPropertyElementMaster;
19652 propAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
19653 ((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio,
NULL);
19655 propAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
19656 ((ma_AudioObjectRemovePropertyListener_proc)pContext->coreaudio.AudioObjectRemovePropertyListener)(kAudioObjectSystemObject, &propAddress, &ma_default_device_changed__coreaudio,
NULL);
19659 ma_assert(g_ppTrackedDevices_CoreAudio ==
NULL);
19660 ma_assert(g_TrackedDeviceCount_CoreAudio == 0);
19672 ma_assert(pDevice !=
NULL);
19674 result = ma_context__init_device_tracking__coreaudio(pDevice->pContext);
19682 if (g_TrackedDeviceCap_CoreAudio <= g_TrackedDeviceCount_CoreAudio) {
19686 newCap = g_TrackedDeviceCap_CoreAudio * 2;
19691 ppNewDevices = (
ma_device**)
ma_realloc(g_ppTrackedDevices_CoreAudio,
sizeof(*g_ppTrackedDevices_CoreAudio) * newCap);
19692 if (ppNewDevices ==
NULL) {
19697 g_ppTrackedDevices_CoreAudio = ppNewDevices;
19698 g_TrackedDeviceCap_CoreAudio = newCap;
19701 g_ppTrackedDevices_CoreAudio[g_TrackedDeviceCount_CoreAudio] = pDevice;
19702 g_TrackedDeviceCount_CoreAudio += 1;
19713 ma_assert(pDevice !=
NULL);
19718 for (iDevice = 0; iDevice < g_TrackedDeviceCount_CoreAudio; iDevice += 1) {
19719 if (g_ppTrackedDevices_CoreAudio[iDevice] == pDevice) {
19722 for (jDevice = iDevice; jDevice < g_TrackedDeviceCount_CoreAudio-1; jDevice += 1) {
19723 g_ppTrackedDevices_CoreAudio[jDevice] = g_ppTrackedDevices_CoreAudio[jDevice+1];
19726 g_TrackedDeviceCount_CoreAudio -= 1;
19729 if (g_TrackedDeviceCount_CoreAudio == 0) {
19730 ma_free(g_ppTrackedDevices_CoreAudio);
19731 g_ppTrackedDevices_CoreAudio =
NULL;
19732 g_TrackedDeviceCap_CoreAudio = 0;
19741 result = ma_context__uninit_device_tracking__coreaudio(pDevice->pContext);
19750 void ma_device_uninit__coreaudio(
ma_device* pDevice)
19752 ma_assert(pDevice !=
NULL);
19753 ma_assert(ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED);
19755 #if defined(MA_APPLE_DESKTOP)
19760 ma_device__untrack__coreaudio(pDevice);
19763 if (pDevice->coreaudio.audioUnitCapture !=
NULL) {
19764 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
19766 if (pDevice->coreaudio.audioUnitPlayback !=
NULL) {
19767 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
19770 if (pDevice->coreaudio.pAudioBufferList) {
19771 ma_free(pDevice->coreaudio.pAudioBufferList);
19797 #if defined(MA_APPLE_DESKTOP)
19798 AudioObjectID deviceObjectID;
19800 AudioComponent component;
19801 AudioUnit audioUnit;
19802 AudioBufferList* pAudioBufferList;
19809 char deviceName[256];
19810 } ma_device_init_internal_data__coreaudio;
19816 UInt32 enableIOFlag;
19817 AudioStreamBasicDescription bestFormat;
19819 AURenderCallbackStruct callbackInfo;
19820 #if defined(MA_APPLE_DESKTOP)
19821 AudioObjectID deviceObjectID;
19829 ma_assert(pContext !=
NULL);
19832 #if defined(MA_APPLE_DESKTOP)
19833 pData->deviceObjectID = 0;
19835 pData->component =
NULL;
19836 pData->audioUnit =
NULL;
19837 pData->pAudioBufferList =
NULL;
19839 #if defined(MA_APPLE_DESKTOP)
19840 result = ma_find_AudioObjectID(pContext, deviceType, pDeviceID, &deviceObjectID);
19845 pData->deviceObjectID = deviceObjectID;
19849 pData->periodsOut = pData->periodsIn;
19850 if (pData->periodsOut == 0) {
19851 pData->periodsOut = MA_DEFAULT_PERIODS;
19853 if (pData->periodsOut > 16) {
19854 pData->periodsOut = 16;
19859 status = ((ma_AudioComponentInstanceNew_proc)pContext->coreaudio.AudioComponentInstanceNew)((AudioComponent)pContext->coreaudio.component, (AudioUnit*)&pData->audioUnit);
19860 if (status != noErr) {
19861 return ma_result_from_OSStatus(status);
19871 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &enableIOFlag,
sizeof(enableIOFlag));
19872 if (status != noErr) {
19873 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19874 return ma_result_from_OSStatus(status);
19877 enableIOFlag = (enableIOFlag == 0) ? 1 : 0;
19878 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &enableIOFlag,
sizeof(enableIOFlag));
19879 if (status != noErr) {
19880 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19881 return ma_result_from_OSStatus(status);
19886 #if defined(MA_APPLE_DESKTOP)
19887 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, (deviceType ==
ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS, &deviceObjectID,
sizeof(AudioDeviceID));
19888 if (status != noErr) {
19889 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19890 return ma_result_from_OSStatus(
result);
19907 AudioUnitScope formatScope = (deviceType ==
ma_device_type_playback) ? kAudioUnitScope_Input : kAudioUnitScope_Output;
19908 AudioUnitElement formatElement = (deviceType ==
ma_device_type_playback) ? MA_COREAUDIO_OUTPUT_BUS : MA_COREAUDIO_INPUT_BUS;
19910 #if defined(MA_APPLE_DESKTOP)
19911 AudioStreamBasicDescription origFormat;
19912 UInt32 origFormatSize;
19914 result = ma_find_best_format__coreaudio(pContext, deviceObjectID, deviceType, pData->formatIn, pData->channelsIn, pData->sampleRateIn, pData->usingDefaultFormat, pData->usingDefaultChannels, pData->usingDefaultSampleRate, &bestFormat);
19916 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19921 origFormatSize =
sizeof(origFormat);
19923 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, MA_COREAUDIO_OUTPUT_BUS, &origFormat, &origFormatSize);
19925 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, MA_COREAUDIO_INPUT_BUS, &origFormat, &origFormatSize);
19928 if (status != noErr) {
19929 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19933 bestFormat.mSampleRate = origFormat.mSampleRate;
19935 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat,
sizeof(bestFormat));
19936 if (status != noErr) {
19938 bestFormat = origFormat;
19941 UInt32 propSize =
sizeof(bestFormat);
19942 status = ((ma_AudioUnitGetProperty_proc)pContext->coreaudio.AudioUnitGetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat, &propSize);
19943 if (status != noErr) {
19944 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19945 return ma_result_from_OSStatus(status);
19955 AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
19956 ma_assert(pAudioSession !=
NULL);
19958 [pAudioSession setPreferredSampleRate:(double)pData->sampleRateIn error:nil];
19959 bestFormat.mSampleRate = pAudioSession.sampleRate;
19962 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_StreamFormat, formatScope, formatElement, &bestFormat,
sizeof(bestFormat));
19963 if (status != noErr) {
19964 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19965 return ma_result_from_OSStatus(status);
19969 result = ma_format_from_AudioStreamBasicDescription(&bestFormat, &pData->formatOut);
19971 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19976 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
19980 pData->channelsOut = bestFormat.mChannelsPerFrame;
19981 pData->sampleRateOut = bestFormat.mSampleRate;
19991 #if defined(MA_APPLE_DESKTOP)
19992 result = ma_get_AudioUnit_channel_map(pContext, pData->audioUnit, deviceType, pData->channelMapOut);
19996 result = ma_get_AudioObject_channel_map(pContext, deviceObjectID, deviceType, pData->channelMapOut);
20012 actualBufferSizeInFrames = pData->bufferSizeInFramesIn;
20014 #if defined(MA_APPLE_DESKTOP)
20015 if (actualBufferSizeInFrames == 0) {
20019 actualBufferSizeInFrames = actualBufferSizeInFrames / pData->periodsOut;
20020 result = ma_set_AudioObject_buffer_size_in_frames(pContext, deviceObjectID, deviceType, &actualBufferSizeInFrames);
20025 pData->bufferSizeInFramesOut = actualBufferSizeInFrames * pData->periodsOut;
20027 actualBufferSizeInFrames = 4096;
20028 pData->bufferSizeInFramesOut = actualBufferSizeInFrames;
20050 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &actualBufferSizeInFrames,
sizeof(actualBufferSizeInFrames));
20051 if (status != noErr) {
20052 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20053 return ma_result_from_OSStatus(status);
20059 ma_bool32 isInterleaved = (bestFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
20060 size_t allocationSize;
20061 AudioBufferList* pBufferList;
20063 allocationSize =
sizeof(AudioBufferList) -
sizeof(
AudioBuffer);
20064 if (isInterleaved) {
20067 allocationSize += actualBufferSizeInFrames * ma_get_bytes_per_frame(pData->formatOut, pData->channelsOut);
20070 allocationSize +=
sizeof(
AudioBuffer) * pData->channelsOut;
20074 pBufferList = (AudioBufferList*)
ma_malloc(allocationSize);
20075 if (pBufferList ==
NULL) {
20076 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20080 if (isInterleaved) {
20081 pBufferList->mNumberBuffers = 1;
20082 pBufferList->mBuffers[0].mNumberChannels = pData->channelsOut;
20083 pBufferList->mBuffers[0].mDataByteSize = actualBufferSizeInFrames * ma_get_bytes_per_frame(pData->formatOut, pData->channelsOut);
20084 pBufferList->mBuffers[0].mData = (
ma_uint8*)pBufferList +
sizeof(AudioBufferList);
20087 pBufferList->mNumberBuffers = pData->channelsOut;
20088 for (iBuffer = 0; iBuffer < pBufferList->mNumberBuffers; ++iBuffer) {
20089 pBufferList->mBuffers[iBuffer].mNumberChannels = 1;
20090 pBufferList->mBuffers[iBuffer].mDataByteSize = actualBufferSizeInFrames *
ma_get_bytes_per_sample(pData->formatOut);
20095 pData->pAudioBufferList = pBufferList;
20099 callbackInfo.inputProcRefCon = pDevice_DoNotReference;
20101 callbackInfo.inputProc = ma_on_output__coreaudio;
20102 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, MA_COREAUDIO_OUTPUT_BUS, &callbackInfo,
sizeof(callbackInfo));
20103 if (status != noErr) {
20104 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20105 return ma_result_from_OSStatus(status);
20108 callbackInfo.inputProc = ma_on_input__coreaudio;
20109 status = ((ma_AudioUnitSetProperty_proc)pContext->coreaudio.AudioUnitSetProperty)(pData->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, MA_COREAUDIO_INPUT_BUS, &callbackInfo,
sizeof(callbackInfo));
20110 if (status != noErr) {
20111 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20112 return ma_result_from_OSStatus(status);
20117 if (pData->registerStopEvent) {
20118 status = ((ma_AudioUnitAddPropertyListener_proc)pContext->coreaudio.AudioUnitAddPropertyListener)(pData->audioUnit, kAudioOutputUnitProperty_IsRunning, on_start_stop__coreaudio, pDevice_DoNotReference);
20119 if (status != noErr) {
20120 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20121 return ma_result_from_OSStatus(status);
20126 status = ((ma_AudioUnitInitialize_proc)pContext->coreaudio.AudioUnitInitialize)(pData->audioUnit);
20127 if (status != noErr) {
20128 ma_free(pData->pAudioBufferList);
20129 pData->pAudioBufferList =
NULL;
20130 ((ma_AudioComponentInstanceDispose_proc)pContext->coreaudio.AudioComponentInstanceDispose)(pData->audioUnit);
20131 return ma_result_from_OSStatus(status);
20135 #if defined(MA_APPLE_DESKTOP)
20136 ma_get_AudioObject_name(pContext, deviceObjectID,
sizeof(pData->deviceName), pData->deviceName);
20139 ma_strcpy_s(pData->deviceName,
sizeof(pData->deviceName), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
20141 ma_strcpy_s(pData->deviceName,
sizeof(pData->deviceName), MA_DEFAULT_CAPTURE_DEVICE_NAME);
20150 ma_device_init_internal_data__coreaudio
data;
20159 data.formatIn = pDevice->capture.format;
20160 data.channelsIn = pDevice->capture.channels;
20161 data.sampleRateIn = pDevice->sampleRate;
20162 ma_copy_memory(
data.channelMapIn, pDevice->capture.channelMap,
sizeof(pDevice->capture.channelMap));
20163 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
20164 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
20165 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
20166 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
20167 data.shareMode = pDevice->capture.shareMode;
20170 if (disposePreviousAudioUnit) {
20171 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20172 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20174 if (pDevice->coreaudio.pAudioBufferList) {
20175 ma_free(pDevice->coreaudio.pAudioBufferList);
20178 data.formatIn = pDevice->playback.format;
20179 data.channelsIn = pDevice->playback.channels;
20180 data.sampleRateIn = pDevice->sampleRate;
20181 ma_copy_memory(
data.channelMapIn, pDevice->playback.channelMap,
sizeof(pDevice->playback.channelMap));
20182 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
20183 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
20184 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
20185 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
20186 data.shareMode = pDevice->playback.shareMode;
20189 if (disposePreviousAudioUnit) {
20190 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20191 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20194 data.bufferSizeInFramesIn = pDevice->coreaudio.originalBufferSizeInFrames;
20195 data.bufferSizeInMillisecondsIn = pDevice->coreaudio.originalBufferSizeInMilliseconds;
20196 data.periodsIn = pDevice->coreaudio.originalPeriods;
20200 data.periodsIn = 3;
20203 result = ma_device_init_internal__coreaudio(pDevice->pContext, deviceType,
NULL, &
data, (
void*)pDevice);
20209 #if defined(MA_APPLE_DESKTOP)
20210 pDevice->coreaudio.deviceObjectIDCapture = (
ma_uint32)
data.deviceObjectID;
20212 pDevice->coreaudio.audioUnitCapture = (
ma_ptr)
data.audioUnit;
20213 pDevice->coreaudio.pAudioBufferList = (
ma_ptr)
data.pAudioBufferList;
20215 pDevice->capture.internalFormat =
data.formatOut;
20216 pDevice->capture.internalChannels =
data.channelsOut;
20217 pDevice->capture.internalSampleRate =
data.sampleRateOut;
20218 ma_copy_memory(pDevice->capture.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
20219 pDevice->capture.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
20220 pDevice->capture.internalPeriods =
data.periodsOut;
20222 #if defined(MA_APPLE_DESKTOP)
20223 pDevice->coreaudio.deviceObjectIDPlayback = (
ma_uint32)
data.deviceObjectID;
20225 pDevice->coreaudio.audioUnitPlayback = (
ma_ptr)
data.audioUnit;
20227 pDevice->playback.internalFormat =
data.formatOut;
20228 pDevice->playback.internalChannels =
data.channelsOut;
20229 pDevice->playback.internalSampleRate =
data.sampleRateOut;
20230 ma_copy_memory(pDevice->playback.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
20231 pDevice->playback.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
20232 pDevice->playback.internalPeriods =
data.periodsOut;
20243 ma_assert(pContext !=
NULL);
20244 ma_assert(pConfig !=
NULL);
20245 ma_assert(pDevice !=
NULL);
20259 ma_device_init_internal_data__coreaudio
data;
20264 data.usingDefaultFormat = pDevice->capture.usingDefaultFormat;
20265 data.usingDefaultChannels = pDevice->capture.usingDefaultChannels;
20266 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
20267 data.usingDefaultChannelMap = pDevice->capture.usingDefaultChannelMap;
20276 data.periodsIn = 3;
20285 #if defined(MA_APPLE_DESKTOP)
20286 pDevice->coreaudio.deviceObjectIDCapture = (
ma_uint32)
data.deviceObjectID;
20288 pDevice->coreaudio.audioUnitCapture = (
ma_ptr)
data.audioUnit;
20289 pDevice->coreaudio.pAudioBufferList = (
ma_ptr)
data.pAudioBufferList;
20291 pDevice->capture.internalFormat =
data.formatOut;
20292 pDevice->capture.internalChannels =
data.channelsOut;
20293 pDevice->capture.internalSampleRate =
data.sampleRateOut;
20294 ma_copy_memory(pDevice->capture.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
20295 pDevice->capture.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
20296 pDevice->capture.internalPeriods =
data.periodsOut;
20298 #if defined(MA_APPLE_DESKTOP)
20304 ma_device__track__coreaudio(pDevice);
20311 ma_device_init_internal_data__coreaudio
data;
20316 data.usingDefaultFormat = pDevice->playback.usingDefaultFormat;
20317 data.usingDefaultChannels = pDevice->playback.usingDefaultChannels;
20318 data.usingDefaultSampleRate = pDevice->usingDefaultSampleRate;
20319 data.usingDefaultChannelMap = pDevice->playback.usingDefaultChannelMap;
20324 data.bufferSizeInFramesIn = pDevice->capture.internalBufferSizeInFrames;
20325 data.periodsIn = pDevice->capture.internalPeriods;
20337 ((ma_AudioComponentInstanceDispose_proc)pDevice->pContext->coreaudio.AudioComponentInstanceDispose)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20338 if (pDevice->coreaudio.pAudioBufferList) {
20339 ma_free(pDevice->coreaudio.pAudioBufferList);
20346 #if defined(MA_APPLE_DESKTOP)
20347 pDevice->coreaudio.deviceObjectIDPlayback = (
ma_uint32)
data.deviceObjectID;
20349 pDevice->coreaudio.audioUnitPlayback = (
ma_ptr)
data.audioUnit;
20351 pDevice->playback.internalFormat =
data.formatOut;
20352 pDevice->playback.internalChannels =
data.channelsOut;
20353 pDevice->playback.internalSampleRate =
data.sampleRateOut;
20354 ma_copy_memory(pDevice->playback.internalChannelMap,
data.channelMapOut,
sizeof(
data.channelMapOut));
20355 pDevice->playback.internalBufferSizeInFrames =
data.bufferSizeInFramesOut;
20356 pDevice->playback.internalPeriods =
data.periodsOut;
20358 #if defined(MA_APPLE_DESKTOP)
20364 ma_device__track__coreaudio(pDevice);
20371 pDevice->coreaudio.originalPeriods = pConfig->
periods;
20377 ma_event_init(pContext, &pDevice->coreaudio.stopEvent);
20381 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
20389 ma_uint32 bufferSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
20393 ma_zero_memory(pBufferData, bufferSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
20405 ma_assert(pDevice !=
NULL);
20408 OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20409 if (status != noErr) {
20410 return ma_result_from_OSStatus(status);
20415 OSStatus status = ((ma_AudioOutputUnitStart_proc)pDevice->pContext->coreaudio.AudioOutputUnitStart)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20416 if (status != noErr) {
20418 ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20420 return ma_result_from_OSStatus(status);
20429 ma_assert(pDevice !=
NULL);
20432 OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitCapture);
20433 if (status != noErr) {
20434 return ma_result_from_OSStatus(status);
20439 OSStatus status = ((ma_AudioOutputUnitStop_proc)pDevice->pContext->coreaudio.AudioOutputUnitStop)((AudioUnit)pDevice->coreaudio.audioUnitPlayback);
20440 if (status != noErr) {
20441 return ma_result_from_OSStatus(status);
20446 ma_event_wait(&pDevice->coreaudio.stopEvent);
20453 ma_assert(pContext !=
NULL);
20456 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
20457 ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
20458 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
20459 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
20468 ma_assert(pContext !=
NULL);
20472 #if defined(MA_APPLE_MOBILE)
20474 AVAudioSession* pAudioSession = [AVAudioSession sharedInstance];
20475 ma_assert(pAudioSession !=
NULL);
20477 [pAudioSession setCategory: AVAudioSessionCategoryPlayAndRecord error:nil];
20482 [pAudioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
20487 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
20488 pContext->coreaudio.hCoreFoundation = ma_dlopen(pContext,
"CoreFoundation.framework/CoreFoundation");
20489 if (pContext->coreaudio.hCoreFoundation ==
NULL) {
20493 pContext->coreaudio.CFStringGetCString = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation,
"CFStringGetCString");
20494 pContext->coreaudio.CFRelease = ma_dlsym(pContext, pContext->coreaudio.hCoreFoundation,
"CFRelease");
20497 pContext->coreaudio.hCoreAudio = ma_dlopen(pContext,
"CoreAudio.framework/CoreAudio");
20498 if (pContext->coreaudio.hCoreAudio ==
NULL) {
20499 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
20503 pContext->coreaudio.AudioObjectGetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectGetPropertyData");
20504 pContext->coreaudio.AudioObjectGetPropertyDataSize = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectGetPropertyDataSize");
20505 pContext->coreaudio.AudioObjectSetPropertyData = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectSetPropertyData");
20506 pContext->coreaudio.AudioObjectAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectAddPropertyListener");
20507 pContext->coreaudio.AudioObjectRemovePropertyListener = ma_dlsym(pContext, pContext->coreaudio.hCoreAudio,
"AudioObjectRemovePropertyListener");
20515 pContext->coreaudio.hAudioUnit = ma_dlopen(pContext,
"AudioUnit.framework/AudioUnit");
20516 if (pContext->coreaudio.hAudioUnit ==
NULL) {
20517 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
20518 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
20522 if (ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentFindNext") ==
NULL) {
20524 ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
20525 pContext->coreaudio.hAudioUnit = ma_dlopen(pContext,
"AudioToolbox.framework/AudioToolbox");
20526 if (pContext->coreaudio.hAudioUnit ==
NULL) {
20527 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
20528 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
20533 pContext->coreaudio.AudioComponentFindNext = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentFindNext");
20534 pContext->coreaudio.AudioComponentInstanceDispose = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentInstanceDispose");
20535 pContext->coreaudio.AudioComponentInstanceNew = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioComponentInstanceNew");
20536 pContext->coreaudio.AudioOutputUnitStart = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioOutputUnitStart");
20537 pContext->coreaudio.AudioOutputUnitStop = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioOutputUnitStop");
20538 pContext->coreaudio.AudioUnitAddPropertyListener = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitAddPropertyListener");
20539 pContext->coreaudio.AudioUnitGetPropertyInfo = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitGetPropertyInfo");
20540 pContext->coreaudio.AudioUnitGetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitGetProperty");
20541 pContext->coreaudio.AudioUnitSetProperty = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitSetProperty");
20542 pContext->coreaudio.AudioUnitInitialize = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitInitialize");
20543 pContext->coreaudio.AudioUnitRender = ma_dlsym(pContext, pContext->coreaudio.hAudioUnit,
"AudioUnitRender");
20545 pContext->coreaudio.CFStringGetCString = (
ma_proc)CFStringGetCString;
20546 pContext->coreaudio.CFRelease = (
ma_proc)CFRelease;
20548 #if defined(MA_APPLE_DESKTOP)
20549 pContext->coreaudio.AudioObjectGetPropertyData = (
ma_proc)AudioObjectGetPropertyData;
20550 pContext->coreaudio.AudioObjectGetPropertyDataSize = (
ma_proc)AudioObjectGetPropertyDataSize;
20551 pContext->coreaudio.AudioObjectSetPropertyData = (
ma_proc)AudioObjectSetPropertyData;
20552 pContext->coreaudio.AudioObjectAddPropertyListener = (
ma_proc)AudioObjectAddPropertyListener;
20553 pContext->coreaudio.AudioObjectRemovePropertyListener = (
ma_proc)AudioObjectRemovePropertyListener;
20556 pContext->coreaudio.AudioComponentFindNext = (
ma_proc)AudioComponentFindNext;
20557 pContext->coreaudio.AudioComponentInstanceDispose = (
ma_proc)AudioComponentInstanceDispose;
20558 pContext->coreaudio.AudioComponentInstanceNew = (
ma_proc)AudioComponentInstanceNew;
20559 pContext->coreaudio.AudioOutputUnitStart = (
ma_proc)AudioOutputUnitStart;
20560 pContext->coreaudio.AudioOutputUnitStop = (
ma_proc)AudioOutputUnitStop;
20561 pContext->coreaudio.AudioUnitAddPropertyListener = (
ma_proc)AudioUnitAddPropertyListener;
20562 pContext->coreaudio.AudioUnitGetPropertyInfo = (
ma_proc)AudioUnitGetPropertyInfo;
20563 pContext->coreaudio.AudioUnitGetProperty = (
ma_proc)AudioUnitGetProperty;
20564 pContext->coreaudio.AudioUnitSetProperty = (
ma_proc)AudioUnitSetProperty;
20565 pContext->coreaudio.AudioUnitInitialize = (
ma_proc)AudioUnitInitialize;
20566 pContext->coreaudio.AudioUnitRender = (
ma_proc)AudioUnitRender;
20571 pContext->
onUninit = ma_context_uninit__coreaudio;
20572 pContext->
onDeviceIDEqual = ma_context_is_device_id_equal__coreaudio;
20573 pContext->
onEnumDevices = ma_context_enumerate_devices__coreaudio;
20582 AudioComponentDescription desc;
20583 desc.componentType = kAudioUnitType_Output;
20584 #if defined(MA_APPLE_DESKTOP)
20585 desc.componentSubType = kAudioUnitSubType_HALOutput;
20587 desc.componentSubType = kAudioUnitSubType_RemoteIO;
20589 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
20590 desc.componentFlags = 0;
20591 desc.componentFlagsMask = 0;
20593 pContext->coreaudio.component = ((ma_AudioComponentFindNext_proc)pContext->coreaudio.AudioComponentFindNext)(
NULL, &desc);
20594 if (pContext->coreaudio.component ==
NULL) {
20595 #if !defined(MA_NO_RUNTIME_LINKING) && !defined(MA_APPLE_MOBILE)
20596 ma_dlclose(pContext, pContext->coreaudio.hAudioUnit);
20597 ma_dlclose(pContext, pContext->coreaudio.hCoreAudio);
20598 ma_dlclose(pContext, pContext->coreaudio.hCoreFoundation);
20615 #ifdef MA_HAS_SNDIO
20617 #include <sys/stat.h>
20626 #if defined(__NetBSD__) || defined(__OpenBSD__)
20627 #include <sys/audioio.h>
20629 #if defined(__FreeBSD__) || defined(__DragonFly__)
20630 #include <sys/soundcard.h>
20634 #define MA_SIO_DEVANY "default"
20635 #define MA_SIO_PLAY 1
20636 #define MA_SIO_REC 2
20637 #define MA_SIO_NENC 8
20638 #define MA_SIO_NCHAN 8
20639 #define MA_SIO_NRATE 16
20640 #define MA_SIO_NCONF 4
20651 unsigned int rchan;
20652 unsigned int pchan;
20654 unsigned int bufsz;
20656 unsigned int round;
20657 unsigned int appbufsz;
20659 unsigned int __magic;
20674 unsigned int rchan;
20675 unsigned int pchan;
20681 struct ma_sio_enc enc[MA_SIO_NENC];
20682 unsigned int rchan[MA_SIO_NCHAN];
20683 unsigned int pchan[MA_SIO_NCHAN];
20684 unsigned int rate[MA_SIO_NRATE];
20686 unsigned int nconf;
20687 struct ma_sio_conf confs[MA_SIO_NCONF];
20690 typedef struct ma_sio_hdl* (* ma_sio_open_proc) (
const char*,
unsigned int,
int);
20691 typedef void (* ma_sio_close_proc) (
struct ma_sio_hdl*);
20692 typedef int (* ma_sio_setpar_proc) (
struct ma_sio_hdl*,
struct ma_sio_par*);
20693 typedef int (* ma_sio_getpar_proc) (
struct ma_sio_hdl*,
struct ma_sio_par*);
20694 typedef int (* ma_sio_getcap_proc) (
struct ma_sio_hdl*,
struct ma_sio_cap*);
20695 typedef size_t (* ma_sio_write_proc) (
struct ma_sio_hdl*,
const void*, size_t);
20696 typedef size_t (* ma_sio_read_proc) (
struct ma_sio_hdl*,
void*, size_t);
20697 typedef int (* ma_sio_start_proc) (
struct ma_sio_hdl*);
20698 typedef int (* ma_sio_stop_proc) (
struct ma_sio_hdl*);
20699 typedef int (* ma_sio_initpar_proc)(
struct ma_sio_par*);
20701 ma_format ma_format_from_sio_enc__sndio(
unsigned int bits,
unsigned int bps,
unsigned int sig,
unsigned int le,
unsigned int msb)
20704 if ((ma_is_little_endian() && le == 0) || (ma_is_big_endian() && le == 1)) {
20708 if (bits == 8 && bps == 1 && sig == 0) {
20711 if (bits == 16 && bps == 2 && sig == 1) {
20714 if (bits == 24 && bps == 3 && sig == 1) {
20717 if (bits == 24 && bps == 4 && sig == 1 && msb == 0) {
20720 if (bits == 32 && bps == 4 && sig == 1) {
20727 ma_format ma_find_best_format_from_sio_cap__sndio(
struct ma_sio_cap* caps)
20730 unsigned int iConfig;
20732 ma_assert(caps !=
NULL);
20735 for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
20736 unsigned int iEncoding;
20737 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
20745 if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
20749 bits = caps->enc[iEncoding].bits;
20750 bps = caps->enc[iEncoding].bps;
20751 sig = caps->enc[iEncoding].sig;
20752 le = caps->enc[iEncoding].le;
20753 msb = caps->enc[iEncoding].msb;
20754 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
20762 if (ma_get_format_priority_index(bestFormat) > ma_get_format_priority_index(
format)) {
20775 unsigned int iConfig;
20777 ma_assert(caps !=
NULL);
20782 for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
20784 unsigned int iEncoding;
20785 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
20786 unsigned int iChannel;
20794 if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
20798 bits = caps->enc[iEncoding].bits;
20799 bps = caps->enc[iEncoding].bps;
20800 sig = caps->enc[iEncoding].sig;
20801 le = caps->enc[iEncoding].le;
20802 msb = caps->enc[iEncoding].msb;
20803 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
20804 if (
format != requiredFormat) {
20809 for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
20810 unsigned int chan = 0;
20811 unsigned int channels;
20814 chan = caps->confs[iConfig].pchan;
20816 chan = caps->confs[iConfig].rchan;
20819 if ((chan & (1UL << iChannel)) == 0) {
20824 channels = caps->pchan[iChannel];
20826 channels = caps->rchan[iChannel];
20829 if (maxChannels < channels) {
20830 maxChannels = channels;
20836 return maxChannels;
20843 unsigned int iConfig;
20845 ma_assert(caps !=
NULL);
20847 ma_assert(requiredChannels > 0);
20850 firstSampleRate = 0;
20851 bestSampleRate = 0;
20853 for (iConfig = 0; iConfig < caps->nconf; iConfig += 1) {
20855 unsigned int iEncoding;
20856 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
20857 unsigned int iChannel;
20865 if ((caps->confs[iConfig].enc & (1UL << iEncoding)) == 0) {
20869 bits = caps->enc[iEncoding].bits;
20870 bps = caps->enc[iEncoding].bps;
20871 sig = caps->enc[iEncoding].sig;
20872 le = caps->enc[iEncoding].le;
20873 msb = caps->enc[iEncoding].msb;
20874 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
20875 if (
format != requiredFormat) {
20880 for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
20881 unsigned int chan = 0;
20882 unsigned int channels;
20883 unsigned int iRate;
20886 chan = caps->confs[iConfig].pchan;
20888 chan = caps->confs[iConfig].rchan;
20891 if ((chan & (1UL << iChannel)) == 0) {
20896 channels = caps->pchan[iChannel];
20898 channels = caps->rchan[iChannel];
20901 if (channels != requiredChannels) {
20906 for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
20910 if (firstSampleRate == 0) {
20911 firstSampleRate = rate;
20915 ratePriority = ma_get_standard_sample_rate_priority_index(rate);
20920 if (ma_get_standard_sample_rate_priority_index(bestSampleRate) > ratePriority) {
20921 bestSampleRate = rate;
20929 if (bestSampleRate == 0) {
20930 bestSampleRate = firstSampleRate;
20933 return bestSampleRate;
20939 ma_assert(pContext !=
NULL);
20940 ma_assert(pID0 !=
NULL);
20941 ma_assert(pID1 !=
NULL);
20944 return ma_strcmp(pID0->sndio, pID1->sndio) == 0;
20950 struct ma_sio_hdl*
handle;
20952 ma_assert(pContext !=
NULL);
20953 ma_assert(callback !=
NULL);
20958 if (!isTerminating) {
20959 handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_PLAY, 0);
20963 ma_zero_object(&deviceInfo);
20964 ma_strcpy_s(deviceInfo.
id.sndio,
sizeof(deviceInfo.
id.sndio), MA_SIO_DEVANY);
20965 ma_strcpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME);
20969 ((ma_sio_close_proc)pContext->sndio.sio_close)(
handle);
20974 if (!isTerminating) {
20975 handle = ((ma_sio_open_proc)pContext->sndio.sio_open)(MA_SIO_DEVANY, MA_SIO_REC, 0);
20979 ma_zero_object(&deviceInfo);
20980 ma_strcpy_s(deviceInfo.
id.sndio,
sizeof(deviceInfo.
id.sndio),
"default");
20981 ma_strcpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME);
20985 ((ma_sio_close_proc)pContext->sndio.sio_close)(
handle);
20995 struct ma_sio_hdl*
handle;
20996 struct ma_sio_cap caps;
20997 unsigned int iConfig;
20999 ma_assert(pContext !=
NULL);
21003 if (pDeviceID ==
NULL) {
21004 ma_strcpy_s(devid,
sizeof(devid), MA_SIO_DEVANY);
21005 ma_strcpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), (deviceType ==
ma_device_type_playback) ? MA_DEFAULT_PLAYBACK_DEVICE_NAME : MA_DEFAULT_CAPTURE_DEVICE_NAME);
21007 ma_strcpy_s(devid,
sizeof(devid), pDeviceID->sndio);
21008 ma_strcpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), devid);
21016 if (((ma_sio_getcap_proc)pContext->sndio.sio_getcap)(
handle, &caps) == 0) {
21020 for (iConfig = 0; iConfig < caps.nconf; iConfig += 1) {
21025 unsigned int iEncoding;
21026 unsigned int iChannel;
21027 unsigned int iRate;
21029 for (iEncoding = 0; iEncoding < MA_SIO_NENC; iEncoding += 1) {
21039 if ((caps.confs[iConfig].enc & (1UL << iEncoding)) == 0) {
21043 bits = caps.enc[iEncoding].bits;
21044 bps = caps.enc[iEncoding].bps;
21045 sig = caps.enc[iEncoding].sig;
21046 le = caps.enc[iEncoding].le;
21047 msb = caps.enc[iEncoding].msb;
21048 format = ma_format_from_sio_enc__sndio(bits, bps, sig, le, msb);
21054 for (iExistingFormat = 0; iExistingFormat < pDeviceInfo->
formatCount; iExistingFormat += 1) {
21061 if (!formatExists) {
21067 for (iChannel = 0; iChannel < MA_SIO_NCHAN; iChannel += 1) {
21068 unsigned int chan = 0;
21069 unsigned int channels;
21072 chan = caps.confs[iConfig].pchan;
21074 chan = caps.confs[iConfig].rchan;
21077 if ((chan & (1UL << iChannel)) == 0) {
21082 channels = caps.pchan[iChannel];
21084 channels = caps.rchan[iChannel];
21096 for (iRate = 0; iRate < MA_SIO_NRATE; iRate += 1) {
21097 if ((caps.confs[iConfig].rate & (1UL << iRate)) != 0) {
21098 unsigned int rate = caps.rate[iRate];
21109 ((ma_sio_close_proc)pContext->sndio.sio_close)(
handle);
21113 void ma_device_uninit__sndio(
ma_device* pDevice)
21115 ma_assert(pDevice !=
NULL);
21118 ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture);
21122 ((ma_sio_close_proc)pDevice->pContext->sndio.sio_close)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
21128 const char* pDeviceName;
21131 struct ma_sio_cap caps;
21132 struct ma_sio_par par;
21143 ma_assert(pContext !=
NULL);
21144 ma_assert(pConfig !=
NULL);
21146 ma_assert(pDevice !=
NULL);
21149 openFlags = MA_SIO_REC;
21155 openFlags = MA_SIO_PLAY;
21162 pDeviceName = MA_SIO_DEVANY;
21163 if (pDeviceID !=
NULL) {
21164 pDeviceName = pDeviceID->sndio;
21167 handle = (
ma_ptr)((ma_sio_open_proc)pContext->sndio.sio_open)(pDeviceName, openFlags, 0);
21173 if (((ma_sio_getcap_proc)pContext->sndio.sio_getcap)((
struct ma_sio_hdl*)
handle, &caps) == 0) {
21174 ((ma_sio_close_proc)pContext->sndio.sio_close)((
struct ma_sio_hdl*)
handle);
21187 if (pDevice->capture.usingDefaultFormat) {
21188 format = ma_find_best_format_from_sio_cap__sndio(&caps);
21190 if (pDevice->capture.usingDefaultChannels) {
21191 if (strlen(pDeviceName) > strlen(
"rsnd/") && strncmp(pDeviceName,
"rsnd/", strlen(
"rsnd/")) == 0) {
21192 channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType,
format);
21196 if (pDevice->playback.usingDefaultFormat) {
21197 format = ma_find_best_format_from_sio_cap__sndio(&caps);
21199 if (pDevice->playback.usingDefaultChannels) {
21200 if (strlen(pDeviceName) > strlen(
"rsnd/") && strncmp(pDeviceName,
"rsnd/", strlen(
"rsnd/")) == 0) {
21201 channels = ma_find_best_channels_from_sio_cap__sndio(&caps, deviceType,
format);
21206 if (pDevice->usingDefaultSampleRate) {
21207 sampleRate = ma_find_best_sample_rate_from_sio_cap__sndio(&caps, pConfig->
deviceType,
format, channels);
21211 ((ma_sio_initpar_proc)pDevice->pContext->sndio.sio_initpar)(&par);
21213 par.le = ma_is_little_endian();
21248 par.rchan = channels;
21250 par.pchan = channels;
21253 par.rate = sampleRate;
21256 if (internalBufferSizeInFrames == 0) {
21260 par.round = internalBufferSizeInFrames / pConfig->
periods;
21261 par.appbufsz = par.round * pConfig->
periods;
21263 if (((ma_sio_setpar_proc)pContext->sndio.sio_setpar)((
struct ma_sio_hdl*)
handle, &par) == 0) {
21264 ((ma_sio_close_proc)pContext->sndio.sio_close)((
struct ma_sio_hdl*)
handle);
21267 if (((ma_sio_getpar_proc)pContext->sndio.sio_getpar)((
struct ma_sio_hdl*)
handle, &par) == 0) {
21268 ((ma_sio_close_proc)pContext->sndio.sio_close)((
struct ma_sio_hdl*)
handle);
21272 internalFormat = ma_format_from_sio_enc__sndio(par.bits, par.bps, par.sig, par.le, par.msb);
21274 internalSampleRate = par.rate;
21275 internalPeriods = par.appbufsz / par.round;
21276 internalBufferSizeInFrames = par.appbufsz;
21279 pDevice->sndio.handleCapture =
handle;
21280 pDevice->capture.internalFormat = internalFormat;
21281 pDevice->capture.internalChannels = internalChannels;
21282 pDevice->capture.internalSampleRate = internalSampleRate;
21284 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
21285 pDevice->capture.internalPeriods = internalPeriods;
21287 pDevice->sndio.handlePlayback =
handle;
21288 pDevice->playback.internalFormat = internalFormat;
21289 pDevice->playback.internalChannels = internalChannels;
21290 pDevice->playback.internalSampleRate = internalSampleRate;
21292 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
21293 pDevice->playback.internalPeriods = internalPeriods;
21296 #ifdef MA_DEBUG_OUTPUT
21297 printf(
"DEVICE INFO\n");
21299 printf(
" Channels: %d\n", internalChannels);
21300 printf(
" Sample Rate: %d\n", internalSampleRate);
21301 printf(
" Buffer Size: %d\n", internalBufferSizeInFrames);
21302 printf(
" Periods: %d\n", internalPeriods);
21303 printf(
" appbufsz: %d\n", par.appbufsz);
21304 printf(
" round: %d\n", par.round);
21312 ma_assert(pDevice !=
NULL);
21314 ma_zero_object(&pDevice->sndio);
21339 ma_assert(pDevice !=
NULL);
21342 ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture);
21346 ((ma_sio_stop_proc)pDevice->pContext->sndio.sio_stop)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
21356 if (pFramesWritten !=
NULL) {
21357 *pFramesWritten = 0;
21360 result = ((ma_sio_write_proc)pDevice->pContext->sndio.sio_write)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
21365 if (pFramesWritten !=
NULL) {
21366 *pFramesWritten = frameCount;
21376 if (pFramesRead !=
NULL) {
21380 result = ((ma_sio_read_proc)pDevice->pContext->sndio.sio_read)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
21385 if (pFramesRead !=
NULL) {
21386 *pFramesRead = frameCount;
21399 ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((
struct ma_sio_hdl*)pDevice->sndio.handleCapture);
21402 ((ma_sio_start_proc)pDevice->pContext->sndio.sio_start)((
struct ma_sio_hdl*)pDevice->sndio.handlePlayback);
21405 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
21406 switch (pDevice->type)
21411 ma_uint8 capturedDeviceData[8192];
21412 ma_uint8 playbackDeviceData[8192];
21413 ma_uint32 capturedDeviceDataCapInFrames =
sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
21414 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
21417 ma_uint32 periodSizeInFrames = ma_min(pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods, pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods);
21419 while (totalFramesProcessed < periodSizeInFrames) {
21420 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
21422 ma_uint32 framesToProcess = framesRemaining;
21423 if (framesToProcess > capturedDeviceDataCapInFrames) {
21424 framesToProcess = capturedDeviceDataCapInFrames;
21427 result = ma_device_read__sndio(pDevice, capturedDeviceData, framesToProcess, &framesProcessed);
21433 pDevice->capture._dspFrameCount = framesToProcess;
21434 pDevice->capture._dspFrames = capturedDeviceData;
21439 ma_uint32 capturedDataCapInFrames =
sizeof(capturedData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
21440 ma_uint32 playbackDataCapInFrames =
sizeof(playbackData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
21442 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
21444 if (capturedFramesToProcess == 0) {
21448 ma_device__on_data(pDevice, playbackData, capturedData, capturedFramesToProcess);
21451 pDevice->playback._dspFrameCount = capturedFramesToProcess;
21452 pDevice->playback._dspFrames = playbackData;
21455 if (playbackDeviceFramesCount == 0) {
21459 result = ma_device_write__sndio(pDevice, playbackDeviceData, playbackDeviceFramesCount,
NULL);
21465 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
21470 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
21481 totalFramesProcessed += framesProcessed;
21488 ma_uint8 intermediaryBuffer[8192];
21489 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
21490 ma_uint32 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
21492 while (framesReadThisPeriod < periodSizeInFrames) {
21493 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
21495 ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
21496 if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
21497 framesToReadThisIteration = intermediaryBufferSizeInFrames;
21500 result = ma_device_read__sndio(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
21506 ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
21508 framesReadThisPeriod += framesProcessed;
21515 ma_uint8 intermediaryBuffer[8192];
21516 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
21517 ma_uint32 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
21519 while (framesWrittenThisPeriod < periodSizeInFrames) {
21520 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
21522 ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
21523 if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
21524 framesToWriteThisIteration = intermediaryBufferSizeInFrames;
21527 ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
21529 result = ma_device_write__sndio(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
21535 framesWrittenThisPeriod += framesProcessed;
21547 ma_device_stop__sndio(pDevice);
21554 ma_assert(pContext !=
NULL);
21563 #ifndef MA_NO_RUNTIME_LINKING
21564 const char* libsndioNames[] = {
21569 for (i = 0; i < ma_countof(libsndioNames); ++i) {
21570 pContext->sndio.sndioSO = ma_dlopen(pContext, libsndioNames[i]);
21571 if (pContext->sndio.sndioSO !=
NULL) {
21576 if (pContext->sndio.sndioSO ==
NULL) {
21580 pContext->sndio.sio_open = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_open");
21581 pContext->sndio.sio_close = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_close");
21582 pContext->sndio.sio_setpar = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_setpar");
21583 pContext->sndio.sio_getpar = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_getpar");
21584 pContext->sndio.sio_getcap = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_getcap");
21585 pContext->sndio.sio_write = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_write");
21586 pContext->sndio.sio_read = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_read");
21587 pContext->sndio.sio_start = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_start");
21588 pContext->sndio.sio_stop = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_stop");
21589 pContext->sndio.sio_initpar = (
ma_proc)ma_dlsym(pContext, pContext->sndio.sndioSO,
"sio_initpar");
21591 pContext->sndio.sio_open = sio_open;
21592 pContext->sndio.sio_close = sio_close;
21593 pContext->sndio.sio_setpar = sio_setpar;
21594 pContext->sndio.sio_getpar = sio_getpar;
21595 pContext->sndio.sio_getcap = sio_getcap;
21596 pContext->sndio.sio_write = sio_write;
21597 pContext->sndio.sio_read = sio_read;
21598 pContext->sndio.sio_start = sio_start;
21599 pContext->sndio.sio_stop = sio_stop;
21600 pContext->sndio.sio_initpar = sio_initpar;
21603 pContext->
onUninit = ma_context_uninit__sndio;
21605 pContext->
onEnumDevices = ma_context_enumerate_devices__sndio;
21625 #ifdef MA_HAS_AUDIO4
21629 #include <sys/stat.h>
21630 #include <sys/types.h>
21631 #include <sys/ioctl.h>
21632 #include <sys/audioio.h>
21634 #if defined(__OpenBSD__)
21635 #include <sys/param.h>
21636 #if defined(OpenBSD) && OpenBSD >= 201709
21637 #define MA_AUDIO4_USE_NEW_API
21641 void ma_construct_device_id__audio4(
char*
id,
size_t idSize,
const char* base,
int deviceIndex)
21645 ma_assert(
id !=
NULL);
21646 ma_assert(idSize > 0);
21647 ma_assert(deviceIndex >= 0);
21649 baseLen = strlen(base);
21650 ma_assert(idSize > baseLen);
21652 ma_strcpy_s(
id, idSize, base);
21653 ma_itoa_s(deviceIndex,
id+baseLen, idSize-baseLen, 10);
21656 ma_result ma_extract_device_index_from_id__audio4(
const char*
id,
const char* base,
int* pIndexOut)
21660 const char* deviceIndexStr;
21662 ma_assert(
id !=
NULL);
21663 ma_assert(base !=
NULL);
21664 ma_assert(pIndexOut !=
NULL);
21666 idLen = strlen(
id);
21667 baseLen = strlen(base);
21668 if (idLen <= baseLen) {
21672 if (strncmp(
id, base, baseLen) != 0) {
21676 deviceIndexStr =
id + baseLen;
21677 if (deviceIndexStr[0] ==
'\0') {
21682 *pIndexOut = atoi(deviceIndexStr);
21690 ma_assert(pContext !=
NULL);
21691 ma_assert(pID0 !=
NULL);
21692 ma_assert(pID1 !=
NULL);
21695 return ma_strcmp(pID0->audio4, pID1->audio4) == 0;
21698 #if !defined(MA_AUDIO4_USE_NEW_API)
21699 ma_format ma_format_from_encoding__audio4(
unsigned int encoding,
unsigned int precision)
21701 if (
precision == 8 && (encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR || encoding == AUDIO_ENCODING_ULINEAR_LE || encoding == AUDIO_ENCODING_ULINEAR_BE)) {
21704 if (ma_is_little_endian() && encoding == AUDIO_ENCODING_SLINEAR_LE) {
21712 }
else if (ma_is_big_endian() && encoding == AUDIO_ENCODING_SLINEAR_BE) {
21726 void ma_encoding_from_format__audio4(
ma_format format,
unsigned int* pEncoding,
unsigned int* pPrecision)
21729 ma_assert(pEncoding !=
NULL);
21730 ma_assert(pPrecision !=
NULL);
21736 *pEncoding = AUDIO_ENCODING_ULINEAR;
21742 *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
21748 *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
21756 *pEncoding = (ma_is_little_endian()) ? AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_SLINEAR_BE;
21762 ma_format ma_format_from_prinfo__audio4(
struct audio_prinfo* prinfo)
21764 return ma_format_from_encoding__audio4(prinfo->encoding, prinfo->precision);
21767 ma_format ma_format_from_swpar__audio4(
struct audio_swpar* par)
21769 if (par->bits == 8 && par->bps == 1 && par->sig == 0) {
21772 if (par->bits == 16 && par->bps == 2 && par->sig == 1 && par->le == ma_is_little_endian()) {
21775 if (par->bits == 24 && par->bps == 3 && par->sig == 1 && par->le == ma_is_little_endian()) {
21778 if (par->bits == 32 && par->bps == 4 && par->sig == 1 && par->le == ma_is_little_endian()) {
21789 audio_device_t fdDevice;
21790 #if !defined(MA_AUDIO4_USE_NEW_API)
21792 audio_info_t fdInfo;
21794 struct audio_swpar fdPar;
21798 ma_assert(pContext !=
NULL);
21799 ma_assert(fd >= 0);
21800 ma_assert(pInfoOut !=
NULL);
21805 if (ioctl(fd, AUDIO_GETDEV, &fdDevice) < 0) {
21810 ma_strcpy_s(pInfoOut->
name,
sizeof(pInfoOut->
name), fdDevice.name);
21812 #if !defined(MA_AUDIO4_USE_NEW_API)
21815 audio_encoding_t encoding;
21818 ma_zero_object(&encoding);
21820 if (ioctl(fd, AUDIO_GETENC, &encoding) < 0) {
21824 format = ma_format_from_encoding__audio4(encoding.encoding, encoding.precision);
21832 if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
21848 if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
21852 format = ma_format_from_swpar__audio4(&fdPar);
21875 const int maxDevices = 64;
21879 ma_assert(pContext !=
NULL);
21880 ma_assert(callback !=
NULL);
21886 for (iDevice = 0; iDevice < maxDevices; ++iDevice) {
21891 ma_strcpy_s(devpath,
sizeof(devpath),
"/dev/audioctl");
21892 ma_itoa_s(iDevice, devpath+strlen(devpath),
sizeof(devpath)-strlen(devpath), 10);
21894 if (stat(devpath, &st) < 0) {
21901 if (!isTerminating) {
21902 fd = open(devpath, O_RDONLY, 0);
21906 ma_zero_object(&deviceInfo);
21907 ma_construct_device_id__audio4(deviceInfo.
id.audio4,
sizeof(deviceInfo.
id.audio4),
"/dev/audio", iDevice);
21917 if (!isTerminating) {
21918 fd = open(devpath, O_WRONLY, 0);
21922 ma_zero_object(&deviceInfo);
21923 ma_construct_device_id__audio4(deviceInfo.
id.audio4,
sizeof(deviceInfo.
id.audio4),
"/dev/audio", iDevice);
21932 if (isTerminating) {
21943 int deviceIndex = -1;
21947 ma_assert(pContext !=
NULL);
21954 if (pDeviceID ==
NULL) {
21956 ma_strcpy_s(ctlid,
sizeof(ctlid),
"/dev/audioctl");
21959 result = ma_extract_device_index_from_id__audio4(pDeviceID->audio4,
"/dev/audio", &deviceIndex);
21964 ma_construct_device_id__audio4(ctlid,
sizeof(ctlid),
"/dev/audioctl", deviceIndex);
21972 if (deviceIndex == -1) {
21973 ma_strcpy_s(pDeviceInfo->
id.audio4,
sizeof(pDeviceInfo->
id.audio4),
"/dev/audio");
21975 ma_construct_device_id__audio4(pDeviceInfo->
id.audio4,
sizeof(pDeviceInfo->
id.audio4),
"/dev/audio", deviceIndex);
21978 result = ma_context_get_device_info_from_fd__audio4(pContext, deviceType, fd, pDeviceInfo);
21984 void ma_device_uninit__audio4(
ma_device* pDevice)
21986 ma_assert(pDevice !=
NULL);
21989 close(pDevice->audio4.fdCapture);
21993 close(pDevice->audio4.fdPlayback);
21999 const char* pDefaultDeviceNames[] = {
22005 #if !defined(MA_AUDIO4_USE_NEW_API)
22006 audio_info_t fdInfo;
22008 struct audio_swpar fdPar;
22016 ma_assert(pContext !=
NULL);
22017 ma_assert(pConfig !=
NULL);
22019 ma_assert(pDevice !=
NULL);
22025 fdFlags = O_RDONLY;
22027 fdFlags = O_WRONLY;
22034 for (iDevice = 0; iDevice < ma_countof(pDefaultDeviceNames); ++iDevice) {
22035 fd = open(pDefaultDeviceNames[iDevice], fdFlags, 0);
22049 #if !defined(MA_AUDIO4_USE_NEW_API)
22050 AUDIO_INITINFO(&fdInfo);
22054 fdInfo.mode = AUMODE_RECORD;
22055 ma_encoding_from_format__audio4(pConfig->
capture.
format, &fdInfo.record.encoding, &fdInfo.record.precision);
22057 fdInfo.record.sample_rate = pConfig->
sampleRate;
22059 fdInfo.mode = AUMODE_PLAY;
22060 ma_encoding_from_format__audio4(pConfig->
playback.
format, &fdInfo.play.encoding, &fdInfo.play.precision);
22062 fdInfo.play.sample_rate = pConfig->
sampleRate;
22065 if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
22070 if (ioctl(fd, AUDIO_GETINFO, &fdInfo) < 0) {
22076 internalFormat = ma_format_from_prinfo__audio4(&fdInfo.record);
22077 internalChannels = fdInfo.record.channels;
22078 internalSampleRate = fdInfo.record.sample_rate;
22080 internalFormat = ma_format_from_prinfo__audio4(&fdInfo.play);
22081 internalChannels = fdInfo.play.channels;
22082 internalSampleRate = fdInfo.play.sample_rate;
22095 if (internalBufferSizeInFrames == 0) {
22099 internalBufferSizeInBytes = internalBufferSizeInFrames * ma_get_bytes_per_frame(internalFormat, internalChannels);
22100 if (internalBufferSizeInBytes < 16) {
22101 internalBufferSizeInBytes = 16;
22104 internalPeriods = pConfig->
periods;
22105 if (internalPeriods < 2) {
22106 internalPeriods = 2;
22110 AUDIO_INITINFO(&fdInfo);
22111 fdInfo.hiwat = internalPeriods;
22112 fdInfo.lowat = internalPeriods-1;
22113 fdInfo.blocksize = internalBufferSizeInBytes / internalPeriods;
22114 if (ioctl(fd, AUDIO_SETINFO, &fdInfo) < 0) {
22119 internalPeriods = fdInfo.hiwat;
22120 internalBufferSizeInFrames = (fdInfo.blocksize * fdInfo.hiwat) / ma_get_bytes_per_frame(internalFormat, internalChannels);
22124 if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
22129 internalFormat = ma_format_from_swpar__audio4(&fdPar);
22131 internalSampleRate = fdPar.rate;
22143 if (internalBufferSizeInFrames == 0) {
22148 internalBufferSizeInBytes = internalBufferSizeInFrames * ma_get_bytes_per_frame(internalFormat, internalChannels);
22149 if (internalBufferSizeInBytes < 16) {
22150 internalBufferSizeInBytes = 16;
22153 fdPar.nblks = pConfig->
periods;
22154 fdPar.round = internalBufferSizeInBytes / fdPar.nblks;
22156 if (ioctl(fd, AUDIO_SETPAR, &fdPar) < 0) {
22161 if (ioctl(fd, AUDIO_GETPAR, &fdPar) < 0) {
22167 internalFormat = ma_format_from_swpar__audio4(&fdPar);
22169 internalSampleRate = fdPar.rate;
22170 internalPeriods = fdPar.nblks;
22171 internalBufferSizeInFrames = (fdPar.nblks * fdPar.round) / ma_get_bytes_per_frame(internalFormat, internalChannels);
22180 pDevice->audio4.fdCapture = fd;
22181 pDevice->capture.internalFormat = internalFormat;
22182 pDevice->capture.internalChannels = internalChannels;
22183 pDevice->capture.internalSampleRate = internalSampleRate;
22185 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
22186 pDevice->capture.internalPeriods = internalPeriods;
22188 pDevice->audio4.fdPlayback = fd;
22189 pDevice->playback.internalFormat = internalFormat;
22190 pDevice->playback.internalChannels = internalChannels;
22191 pDevice->playback.internalSampleRate = internalSampleRate;
22193 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
22194 pDevice->playback.internalPeriods = internalPeriods;
22202 ma_assert(pDevice !=
NULL);
22204 ma_zero_object(&pDevice->audio4);
22210 pDevice->audio4.fdCapture = -1;
22211 pDevice->audio4.fdPlayback = -1;
22218 #if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 800000000
22239 close(pDevice->audio4.fdCapture);
22251 ma_assert(pDevice !=
NULL);
22254 if (pDevice->audio4.fdCapture == -1) {
22260 if (pDevice->audio4.fdPlayback == -1) {
22275 #if !defined(MA_AUDIO4_USE_NEW_API)
22276 if (ioctl(fd, AUDIO_FLUSH, 0) < 0) {
22280 if (ioctl(fd, AUDIO_STOP, 0) < 0) {
22290 ma_assert(pDevice !=
NULL);
22293 ma_result result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdCapture);
22300 ma_result result = ma_device_stop_fd__audio4(pDevice, pDevice->audio4.fdPlayback);
22313 if (pFramesWritten !=
NULL) {
22314 *pFramesWritten = 0;
22317 result = write(pDevice->audio4.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
22322 if (pFramesWritten !=
NULL) {
22323 *pFramesWritten = (
ma_uint32)
result / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22333 if (pFramesRead !=
NULL) {
22337 result = read(pDevice->audio4.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
22342 if (pFramesRead !=
NULL) {
22343 *pFramesRead = (
ma_uint32)
result / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22356 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
22357 switch (pDevice->type)
22362 ma_uint8 capturedDeviceData[8192];
22363 ma_uint8 playbackDeviceData[8192];
22364 ma_uint32 capturedDeviceDataCapInFrames =
sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22365 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22368 ma_uint32 periodSizeInFrames = ma_min(pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods, pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods);
22370 while (totalFramesProcessed < periodSizeInFrames) {
22371 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
22373 ma_uint32 framesToProcess = framesRemaining;
22374 if (framesToProcess > capturedDeviceDataCapInFrames) {
22375 framesToProcess = capturedDeviceDataCapInFrames;
22378 result = ma_device_read__audio4(pDevice, capturedDeviceData, framesToProcess, &framesProcessed);
22384 pDevice->capture._dspFrameCount = framesToProcess;
22385 pDevice->capture._dspFrames = capturedDeviceData;
22390 ma_uint32 capturedDataCapInFrames =
sizeof(capturedData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
22391 ma_uint32 playbackDataCapInFrames =
sizeof(playbackData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
22393 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
22395 if (capturedFramesToProcess == 0) {
22399 ma_device__on_data(pDevice, playbackData, capturedData, capturedFramesToProcess);
22402 pDevice->playback._dspFrameCount = capturedFramesToProcess;
22403 pDevice->playback._dspFrames = playbackData;
22406 if (playbackDeviceFramesCount == 0) {
22410 result = ma_device_write__audio4(pDevice, playbackDeviceData, playbackDeviceFramesCount,
NULL);
22416 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
22421 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
22432 totalFramesProcessed += framesProcessed;
22439 ma_uint8 intermediaryBuffer[8192];
22440 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22441 ma_uint32 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
22443 while (framesReadThisPeriod < periodSizeInFrames) {
22444 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
22446 ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
22447 if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
22448 framesToReadThisIteration = intermediaryBufferSizeInFrames;
22451 result = ma_device_read__audio4(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
22457 ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
22459 framesReadThisPeriod += framesProcessed;
22466 ma_uint8 intermediaryBuffer[8192];
22467 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22468 ma_uint32 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
22470 while (framesWrittenThisPeriod < periodSizeInFrames) {
22471 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
22473 ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
22474 if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
22475 framesToWriteThisIteration = intermediaryBufferSizeInFrames;
22478 ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
22480 result = ma_device_write__audio4(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
22486 framesWrittenThisPeriod += framesProcessed;
22498 ma_device_stop__audio4(pDevice);
22505 ma_assert(pContext !=
NULL);
22514 ma_assert(pContext !=
NULL);
22518 pContext->
onUninit = ma_context_uninit__audio4;
22520 pContext->
onEnumDevices = ma_context_enumerate_devices__audio4;
22539 #include <sys/ioctl.h>
22540 #include <unistd.h>
22542 #include <sys/soundcard.h>
22544 #ifndef SNDCTL_DSP_HALT
22545 #define SNDCTL_DSP_HALT SNDCTL_DSP_RESET
22548 int ma_open_temp_device__oss()
22551 int fd = open(
"/dev/mixer", O_RDONLY, 0);
22561 const char* deviceName;
22564 ma_assert(pContext !=
NULL);
22565 ma_assert(pfd !=
NULL);
22575 deviceName =
"/dev/dsp";
22576 if (pDeviceID !=
NULL) {
22577 deviceName = pDeviceID->oss;
22585 *pfd = open(deviceName,
flags, 0);
22595 ma_assert(pContext !=
NULL);
22596 ma_assert(pID0 !=
NULL);
22597 ma_assert(pID1 !=
NULL);
22600 return ma_strcmp(pID0->oss, pID1->oss) == 0;
22609 ma_assert(pContext !=
NULL);
22610 ma_assert(callback !=
NULL);
22612 fd = ma_open_temp_device__oss();
22614 return ma_context_post_error(pContext,
NULL,
MA_LOG_LEVEL_ERROR,
"[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.",
MA_NO_BACKEND);
22617 result = ioctl(fd, SNDCTL_SYSINFO, &si);
22620 for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
22622 ai.dev = iAudioDevice;
22623 result = ioctl(fd, SNDCTL_AUDIOINFO, &ai);
22625 if (ai.devnode[0] !=
'\0') {
22629 ma_zero_object(&deviceInfo);
22632 ma_strncpy_s(deviceInfo.
id.oss,
sizeof(deviceInfo.
id.oss), ai.devnode, (
size_t)-1);
22639 if (ai.handle[0] !=
'\0') {
22640 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), ai.handle, (
size_t)-1);
22642 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), ai.name, (
size_t)-1);
22646 if (!isTerminating && (ai.caps & PCM_CAP_OUTPUT) != 0) {
22649 if (!isTerminating && (ai.caps & PCM_CAP_INPUT) != 0) {
22653 if (isTerminating) {
22675 ma_assert(pContext !=
NULL);
22679 if (pDeviceID ==
NULL) {
22681 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
22683 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
22693 fdTemp = ma_open_temp_device__oss();
22694 if (fdTemp == -1) {
22695 return ma_context_post_error(pContext,
NULL,
MA_LOG_LEVEL_ERROR,
"[OSS] Failed to open a temporary device for retrieving system information used for device enumeration.",
MA_NO_BACKEND);
22698 result = ioctl(fdTemp, SNDCTL_SYSINFO, &si);
22701 for (iAudioDevice = 0; iAudioDevice < si.numaudios; ++iAudioDevice) {
22703 ai.dev = iAudioDevice;
22704 result = ioctl(fdTemp, SNDCTL_AUDIOINFO, &ai);
22706 if (ma_strcmp(ai.devnode, pDeviceID->oss) == 0) {
22710 unsigned int formatMask;
22713 ma_strncpy_s(pDeviceInfo->
id.oss,
sizeof(pDeviceInfo->
id.oss), ai.devnode, (
size_t)-1);
22720 if (ai.handle[0] !=
'\0') {
22721 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), ai.handle, (
size_t)-1);
22723 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), ai.name, (
size_t)-1);
22733 formatMask = ai.oformats;
22735 formatMask = ai.iformats;
22738 if ((formatMask & AFMT_U8) != 0) {
22741 if (((formatMask & AFMT_S16_LE) != 0 && ma_is_little_endian()) || (AFMT_S16_BE && ma_is_big_endian())) {
22744 if (((formatMask & AFMT_S32_LE) != 0 && ma_is_little_endian()) || (AFMT_S32_BE && ma_is_big_endian())) {
22762 if (!foundDevice) {
22769 void ma_device_uninit__oss(
ma_device* pDevice)
22771 ma_assert(pDevice !=
NULL);
22774 close(pDevice->oss.fdCapture);
22778 close(pDevice->oss.fdPlayback);
22784 int ossFormat = AFMT_U8;
22786 case ma_format_s16: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE;
break;
22787 case ma_format_s24: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE;
break;
22788 case ma_format_s32: ossFormat = (ma_is_little_endian()) ? AFMT_S32_LE : AFMT_S32_BE;
break;
22789 case ma_format_f32: ossFormat = (ma_is_little_endian()) ? AFMT_S16_LE : AFMT_S16_BE;
break;
22791 default: ossFormat = AFMT_U8;
break;
22797 ma_format ma_format_from_oss(
int ossFormat)
22799 if (ossFormat == AFMT_U8) {
22802 if (ma_is_little_endian()) {
22803 switch (ossFormat) {
22809 switch (ossFormat) {
22832 ma_assert(pContext !=
NULL);
22833 ma_assert(pConfig !=
NULL);
22835 ma_assert(pDevice !=
NULL);
22853 result = ma_context_open_device__oss(pContext, deviceType, pDeviceID, shareMode, &fd);
22866 ossResult = ioctl(fd, SNDCTL_DSP_SETFMT, &ossFormat);
22867 if (ossResult == -1) {
22873 ossResult = ioctl(fd, SNDCTL_DSP_CHANNELS, &ossChannels);
22874 if (ossResult == -1) {
22880 ossResult = ioctl(fd, SNDCTL_DSP_SPEED, &ossSampleRate);
22881 if (ossResult == -1) {
22901 if (bufferSizeInFrames == 0) {
22905 fragmentSizeInBytes = ma_round_to_power_of_2((bufferSizeInFrames / pConfig->
periods) * ma_get_bytes_per_frame(ma_format_from_oss(ossFormat), ossChannels));
22906 if (fragmentSizeInBytes < 16) {
22907 fragmentSizeInBytes = 16;
22910 ossFragmentSizePower = 4;
22911 fragmentSizeInBytes >>= 4;
22912 while (fragmentSizeInBytes >>= 1) {
22913 ossFragmentSizePower += 1;
22916 ossFragment = (
int)((pConfig->
periods << 16) | ossFragmentSizePower);
22917 ossResult = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossFragment);
22918 if (ossResult == -1) {
22926 pDevice->oss.fdCapture = fd;
22927 pDevice->capture.internalFormat = ma_format_from_oss(ossFormat);
22928 pDevice->capture.internalChannels = ossChannels;
22929 pDevice->capture.internalSampleRate = ossSampleRate;
22931 pDevice->capture.internalPeriods = (
ma_uint32)(ossFragment >> 16);
22932 pDevice->capture.internalBufferSizeInFrames = (((
ma_uint32)(1 << (ossFragment & 0xFFFF))) * pDevice->capture.internalPeriods) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
22938 pDevice->oss.fdPlayback = fd;
22939 pDevice->playback.internalFormat = ma_format_from_oss(ossFormat);
22940 pDevice->playback.internalChannels = ossChannels;
22941 pDevice->playback.internalSampleRate = ossSampleRate;
22943 pDevice->playback.internalPeriods = (
ma_uint32)(ossFragment >> 16);
22944 pDevice->playback.internalBufferSizeInFrames = (((
ma_uint32)(1 << (ossFragment & 0xFFFF))) * pDevice->playback.internalPeriods) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
22956 ma_assert(pContext !=
NULL);
22957 ma_assert(pConfig !=
NULL);
22958 ma_assert(pDevice !=
NULL);
22960 ma_zero_object(&pDevice->oss);
22985 ma_assert(pDevice !=
NULL);
23001 int result = ioctl(pDevice->oss.fdCapture, SNDCTL_DSP_HALT, 0);
23008 int result = ioctl(pDevice->oss.fdPlayback, SNDCTL_DSP_HALT, 0);
23021 if (pFramesWritten !=
NULL) {
23022 *pFramesWritten = 0;
23025 resultOSS = write(pDevice->oss.fdPlayback, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
23026 if (resultOSS < 0) {
23030 if (pFramesWritten !=
NULL) {
23031 *pFramesWritten = (
ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
23041 if (pFramesRead !=
NULL) {
23045 resultOSS = read(pDevice->oss.fdCapture, pPCMFrames, frameCount * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels));
23046 if (resultOSS < 0) {
23050 if (pFramesRead !=
NULL) {
23051 *pFramesRead = (
ma_uint32)resultOSS / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
23064 while (ma_device__get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
23065 switch (pDevice->type)
23070 ma_uint8 capturedDeviceData[8192];
23071 ma_uint8 playbackDeviceData[8192];
23072 ma_uint32 capturedDeviceDataCapInFrames =
sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
23073 ma_uint32 playbackDeviceDataCapInFrames =
sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
23076 ma_uint32 periodSizeInFrames = ma_min(pDevice->capture.internalBufferSizeInFrames/pDevice->capture.internalPeriods, pDevice->playback.internalBufferSizeInFrames/pDevice->playback.internalPeriods);
23078 while (totalFramesProcessed < periodSizeInFrames) {
23079 ma_uint32 framesRemaining = periodSizeInFrames - totalFramesProcessed;
23081 ma_uint32 framesToProcess = framesRemaining;
23082 if (framesToProcess > capturedDeviceDataCapInFrames) {
23083 framesToProcess = capturedDeviceDataCapInFrames;
23086 result = ma_device_read__oss(pDevice, capturedDeviceData, framesToProcess, &framesProcessed);
23092 pDevice->capture._dspFrameCount = framesToProcess;
23093 pDevice->capture._dspFrames = capturedDeviceData;
23098 ma_uint32 capturedDataCapInFrames =
sizeof(capturedData) / ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
23099 ma_uint32 playbackDataCapInFrames =
sizeof(playbackData) / ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
23101 ma_uint32 capturedFramesToTryProcessing = ma_min(capturedDataCapInFrames, playbackDataCapInFrames);
23103 if (capturedFramesToProcess == 0) {
23107 ma_device__on_data(pDevice, playbackData, capturedData, capturedFramesToProcess);
23110 pDevice->playback._dspFrameCount = capturedFramesToProcess;
23111 pDevice->playback._dspFrames = playbackData;
23114 if (playbackDeviceFramesCount == 0) {
23118 result = ma_device_write__oss(pDevice, playbackDeviceData, playbackDeviceFramesCount,
NULL);
23124 if (playbackDeviceFramesCount < playbackDeviceDataCapInFrames) {
23129 if (capturedFramesToProcess < capturedFramesToTryProcessing) {
23140 totalFramesProcessed += framesProcessed;
23147 ma_uint8 intermediaryBuffer[8192];
23148 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
23149 ma_uint32 periodSizeInFrames = pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods;
23151 while (framesReadThisPeriod < periodSizeInFrames) {
23152 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesReadThisPeriod;
23154 ma_uint32 framesToReadThisIteration = framesRemainingInPeriod;
23155 if (framesToReadThisIteration > intermediaryBufferSizeInFrames) {
23156 framesToReadThisIteration = intermediaryBufferSizeInFrames;
23159 result = ma_device_read__oss(pDevice, intermediaryBuffer, framesToReadThisIteration, &framesProcessed);
23165 ma_device__send_frames_to_client(pDevice, framesProcessed, intermediaryBuffer);
23167 framesReadThisPeriod += framesProcessed;
23174 ma_uint8 intermediaryBuffer[8192];
23175 ma_uint32 intermediaryBufferSizeInFrames =
sizeof(intermediaryBuffer) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
23176 ma_uint32 periodSizeInFrames = pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods;
23178 while (framesWrittenThisPeriod < periodSizeInFrames) {
23179 ma_uint32 framesRemainingInPeriod = periodSizeInFrames - framesWrittenThisPeriod;
23181 ma_uint32 framesToWriteThisIteration = framesRemainingInPeriod;
23182 if (framesToWriteThisIteration > intermediaryBufferSizeInFrames) {
23183 framesToWriteThisIteration = intermediaryBufferSizeInFrames;
23186 ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, intermediaryBuffer);
23188 result = ma_device_write__oss(pDevice, intermediaryBuffer, framesToWriteThisIteration, &framesProcessed);
23194 framesWrittenThisPeriod += framesProcessed;
23206 ma_device_stop__oss(pDevice);
23213 ma_assert(pContext !=
NULL);
23226 ma_assert(pContext !=
NULL);
23231 fd = ma_open_temp_device__oss();
23238 result = ioctl(fd, OSS_GETVERSION, &ossVersion);
23244 pContext->oss.versionMajor = ((ossVersion & 0xFF0000) >> 16);
23245 pContext->oss.versionMinor = ((ossVersion & 0x00FF00) >> 8);
23247 pContext->
onUninit = ma_context_uninit__oss;
23249 pContext->
onEnumDevices = ma_context_enumerate_devices__oss;
23268 #ifdef MA_HAS_AAUDIO
23271 #define MA_AAUDIO_UNSPECIFIED 0
23273 typedef int32_t ma_aaudio_result_t;
23274 typedef int32_t ma_aaudio_direction_t;
23275 typedef int32_t ma_aaudio_sharing_mode_t;
23276 typedef int32_t ma_aaudio_format_t;
23277 typedef int32_t ma_aaudio_stream_state_t;
23278 typedef int32_t ma_aaudio_performance_mode_t;
23279 typedef int32_t ma_aaudio_data_callback_result_t;
23282 #define MA_AAUDIO_OK 0
23285 #define MA_AAUDIO_DIRECTION_OUTPUT 0
23286 #define MA_AAUDIO_DIRECTION_INPUT 1
23289 #define MA_AAUDIO_SHARING_MODE_EXCLUSIVE 0
23290 #define MA_AAUDIO_SHARING_MODE_SHARED 1
23293 #define MA_AAUDIO_FORMAT_PCM_I16 1
23294 #define MA_AAUDIO_FORMAT_PCM_FLOAT 2
23297 #define MA_AAUDIO_STREAM_STATE_UNINITIALIZED 0
23298 #define MA_AAUDIO_STREAM_STATE_UNKNOWN 1
23299 #define MA_AAUDIO_STREAM_STATE_OPEN 2
23300 #define MA_AAUDIO_STREAM_STATE_STARTING 3
23301 #define MA_AAUDIO_STREAM_STATE_STARTED 4
23302 #define MA_AAUDIO_STREAM_STATE_PAUSING 5
23303 #define MA_AAUDIO_STREAM_STATE_PAUSED 6
23304 #define MA_AAUDIO_STREAM_STATE_FLUSHING 7
23305 #define MA_AAUDIO_STREAM_STATE_FLUSHED 8
23306 #define MA_AAUDIO_STREAM_STATE_STOPPING 9
23307 #define MA_AAUDIO_STREAM_STATE_STOPPED 10
23308 #define MA_AAUDIO_STREAM_STATE_CLOSING 11
23309 #define MA_AAUDIO_STREAM_STATE_CLOSED 12
23310 #define MA_AAUDIO_STREAM_STATE_DISCONNECTED 13
23313 #define MA_AAUDIO_PERFORMANCE_MODE_NONE 10
23314 #define MA_AAUDIO_PERFORMANCE_MODE_POWER_SAVING 11
23315 #define MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY 12
23318 #define MA_AAUDIO_CALLBACK_RESULT_CONTINUE 0
23319 #define MA_AAUDIO_CALLBACK_RESULT_STOP 1
23322 typedef struct ma_AAudioStreamBuilder_t* ma_AAudioStreamBuilder;
23323 typedef struct ma_AAudioStream_t* ma_AAudioStream;
23325 typedef ma_aaudio_data_callback_result_t (*ma_AAudioStream_dataCallback)(ma_AAudioStream* pStream,
void* pUserData,
void* pAudioData,
int32_t numFrames);
23327 typedef ma_aaudio_result_t (* MA_PFN_AAudio_createStreamBuilder) (ma_AAudioStreamBuilder** ppBuilder);
23328 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_delete) (ma_AAudioStreamBuilder* pBuilder);
23329 typedef void (* MA_PFN_AAudioStreamBuilder_setDeviceId) (ma_AAudioStreamBuilder* pBuilder,
int32_t deviceId);
23330 typedef void (* MA_PFN_AAudioStreamBuilder_setDirection) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_direction_t direction);
23331 typedef void (* MA_PFN_AAudioStreamBuilder_setSharingMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_sharing_mode_t sharingMode);
23332 typedef void (* MA_PFN_AAudioStreamBuilder_setFormat) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_format_t
format);
23333 typedef void (* MA_PFN_AAudioStreamBuilder_setChannelCount) (ma_AAudioStreamBuilder* pBuilder,
int32_t channelCount);
23334 typedef void (* MA_PFN_AAudioStreamBuilder_setSampleRate) (ma_AAudioStreamBuilder* pBuilder,
int32_t sampleRate);
23335 typedef void (* MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)(ma_AAudioStreamBuilder* pBuilder,
int32_t numFrames);
23336 typedef void (* MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback) (ma_AAudioStreamBuilder* pBuilder,
int32_t numFrames);
23337 typedef void (* MA_PFN_AAudioStreamBuilder_setDataCallback) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream_dataCallback callback,
void* pUserData);
23338 typedef void (* MA_PFN_AAudioStreamBuilder_setPerformanceMode) (ma_AAudioStreamBuilder* pBuilder, ma_aaudio_performance_mode_t
mode);
23339 typedef ma_aaudio_result_t (* MA_PFN_AAudioStreamBuilder_openStream) (ma_AAudioStreamBuilder* pBuilder, ma_AAudioStream** ppStream);
23340 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_close) (ma_AAudioStream* pStream);
23341 typedef ma_aaudio_stream_state_t (* MA_PFN_AAudioStream_getState) (ma_AAudioStream* pStream);
23342 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_waitForStateChange) (ma_AAudioStream* pStream, ma_aaudio_stream_state_t inputState, ma_aaudio_stream_state_t* pNextState,
int64_t timeoutInNanoseconds);
23343 typedef ma_aaudio_format_t (* MA_PFN_AAudioStream_getFormat) (ma_AAudioStream* pStream);
23344 typedef int32_t (* MA_PFN_AAudioStream_getChannelCount) (ma_AAudioStream* pStream);
23345 typedef int32_t (* MA_PFN_AAudioStream_getSampleRate) (ma_AAudioStream* pStream);
23346 typedef int32_t (* MA_PFN_AAudioStream_getBufferCapacityInFrames) (ma_AAudioStream* pStream);
23347 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerDataCallback) (ma_AAudioStream* pStream);
23348 typedef int32_t (* MA_PFN_AAudioStream_getFramesPerBurst) (ma_AAudioStream* pStream);
23349 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStart) (ma_AAudioStream* pStream);
23350 typedef ma_aaudio_result_t (* MA_PFN_AAudioStream_requestStop) (ma_AAudioStream* pStream);
23352 ma_result ma_result_from_aaudio(ma_aaudio_result_t resultAA)
23363 ma_aaudio_data_callback_result_t ma_stream_data_callback_capture__aaudio(ma_AAudioStream* pStream,
void* pUserData,
void* pAudioData,
int32_t frameCount)
23366 ma_assert(pDevice !=
NULL);
23369 ma_device__handle_duplex_callback_capture(pDevice, frameCount, pAudioData, &pDevice->aaudio.duplexRB);
23371 ma_device__send_frames_to_client(pDevice, frameCount, pAudioData);
23375 return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
23378 ma_aaudio_data_callback_result_t ma_stream_data_callback_playback__aaudio(ma_AAudioStream* pStream,
void* pUserData,
void* pAudioData,
int32_t frameCount)
23381 ma_assert(pDevice !=
NULL);
23384 ma_device__handle_duplex_callback_playback(pDevice, frameCount, pAudioData, &pDevice->aaudio.duplexRB);
23386 ma_device__read_frames_from_client(pDevice, frameCount, pAudioData);
23390 return MA_AAUDIO_CALLBACK_RESULT_CONTINUE;
23395 ma_AAudioStreamBuilder* pBuilder;
23396 ma_aaudio_result_t resultAA;
23402 resultAA = ((MA_PFN_AAudio_createStreamBuilder)pContext->aaudio.AAudio_createStreamBuilder)(&pBuilder);
23403 if (resultAA != MA_AAUDIO_OK) {
23404 return ma_result_from_aaudio(resultAA);
23407 if (pDeviceID !=
NULL) {
23408 ((MA_PFN_AAudioStreamBuilder_setDeviceId)pContext->aaudio.AAudioStreamBuilder_setDeviceId)(pBuilder, pDeviceID->aaudio);
23411 ((MA_PFN_AAudioStreamBuilder_setDirection)pContext->aaudio.AAudioStreamBuilder_setDirection)(pBuilder, (deviceType ==
ma_device_type_playback) ? MA_AAUDIO_DIRECTION_OUTPUT : MA_AAUDIO_DIRECTION_INPUT);
23412 ((MA_PFN_AAudioStreamBuilder_setSharingMode)pContext->aaudio.AAudioStreamBuilder_setSharingMode)(pBuilder, (shareMode ==
ma_share_mode_shared) ? MA_AAUDIO_SHARING_MODE_SHARED : MA_AAUDIO_SHARING_MODE_EXCLUSIVE);
23414 if (pConfig !=
NULL) {
23417 if (pDevice ==
NULL || !pDevice->usingDefaultSampleRate) {
23418 ((MA_PFN_AAudioStreamBuilder_setSampleRate)pContext->aaudio.AAudioStreamBuilder_setSampleRate)(pBuilder, pConfig->
sampleRate);
23422 if (pDevice ==
NULL || !pDevice->capture.usingDefaultChannels) {
23423 ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pConfig->
capture.
channels);
23425 if (pDevice ==
NULL || !pDevice->capture.usingDefaultFormat) {
23426 ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pConfig->
capture.
format ==
ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
23429 if (pDevice ==
NULL || !pDevice->playback.usingDefaultChannels) {
23430 ((MA_PFN_AAudioStreamBuilder_setChannelCount)pContext->aaudio.AAudioStreamBuilder_setChannelCount)(pBuilder, pConfig->
playback.
channels);
23432 if (pDevice ==
NULL || !pDevice->playback.usingDefaultFormat) {
23433 ((MA_PFN_AAudioStreamBuilder_setFormat)pContext->aaudio.AAudioStreamBuilder_setFormat)(pBuilder, (pConfig->
playback.
format ==
ma_format_s16) ? MA_AAUDIO_FORMAT_PCM_I16 : MA_AAUDIO_FORMAT_PCM_FLOAT);
23438 if (bufferCapacityInFrames == 0) {
23441 bufferCapacityInFrames = (bufferCapacityInFrames / pConfig->
periods) * pConfig->
periods;
23442 ((MA_PFN_AAudioStreamBuilder_setBufferCapacityInFrames)pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames)(pBuilder, bufferCapacityInFrames);
23444 ((MA_PFN_AAudioStreamBuilder_setFramesPerDataCallback)pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback)(pBuilder, bufferCapacityInFrames / pConfig->
periods);
23447 ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_capture__aaudio, (
void*)pDevice);
23449 ((MA_PFN_AAudioStreamBuilder_setDataCallback)pContext->aaudio.AAudioStreamBuilder_setDataCallback)(pBuilder, ma_stream_data_callback_playback__aaudio, (
void*)pDevice);
23453 ((MA_PFN_AAudioStreamBuilder_setPerformanceMode)pContext->aaudio.AAudioStreamBuilder_setPerformanceMode)(pBuilder, (pConfig->
performanceProfile ==
ma_performance_profile_low_latency) ? MA_AAUDIO_PERFORMANCE_MODE_LOW_LATENCY : MA_AAUDIO_PERFORMANCE_MODE_NONE);
23456 resultAA = ((MA_PFN_AAudioStreamBuilder_openStream)pContext->aaudio.AAudioStreamBuilder_openStream)(pBuilder, ppStream);
23457 if (resultAA != MA_AAUDIO_OK) {
23459 ((MA_PFN_AAudioStreamBuilder_delete)pContext->aaudio.AAudioStreamBuilder_delete)(pBuilder);
23460 return ma_result_from_aaudio(resultAA);
23463 ((MA_PFN_AAudioStreamBuilder_delete)pContext->aaudio.AAudioStreamBuilder_delete)(pBuilder);
23469 return ma_result_from_aaudio(((MA_PFN_AAudioStream_close)pContext->aaudio.AAudioStream_close)(pStream));
23475 ma_AAudioStream* pStream;
23481 ma_close_stream__aaudio(pContext, pStream);
23485 ma_result ma_wait_for_simple_state_transition__aaudio(
ma_context* pContext, ma_AAudioStream* pStream, ma_aaudio_stream_state_t oldState, ma_aaudio_stream_state_t newState)
23487 ma_aaudio_stream_state_t actualNewState;
23488 ma_aaudio_result_t resultAA = ((MA_PFN_AAudioStream_waitForStateChange)pContext->aaudio.AAudioStream_waitForStateChange)(pStream, oldState, &actualNewState, 5000000000);
23489 if (resultAA != MA_AAUDIO_OK) {
23490 return ma_result_from_aaudio(resultAA);
23493 if (newState != actualNewState) {
23503 ma_assert(pContext !=
NULL);
23504 ma_assert(pID0 !=
NULL);
23505 ma_assert(pID1 !=
NULL);
23508 return pID0->aaudio == pID1->aaudio;
23515 ma_assert(pContext !=
NULL);
23516 ma_assert(callback !=
NULL);
23523 ma_zero_object(&deviceInfo);
23524 deviceInfo.
id.aaudio = MA_AAUDIO_UNSPECIFIED;
23525 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
23535 ma_zero_object(&deviceInfo);
23536 deviceInfo.
id.aaudio = MA_AAUDIO_UNSPECIFIED;
23537 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
23549 ma_AAudioStream* pStream;
23552 ma_assert(pContext !=
NULL);
23560 if (pDeviceID !=
NULL) {
23561 pDeviceInfo->
id.aaudio = pDeviceID->aaudio;
23563 pDeviceInfo->
id.aaudio = MA_AAUDIO_UNSPECIFIED;
23568 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
23570 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
23575 result = ma_open_stream__aaudio(pContext, deviceType, pDeviceID, shareMode,
NULL,
NULL, &pStream);
23580 pDeviceInfo->
minChannels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)(pStream);
23582 pDeviceInfo->
minSampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)(pStream);
23585 ma_close_stream__aaudio(pContext, pStream);
23598 void ma_device_uninit__aaudio(
ma_device* pDevice)
23600 ma_assert(pDevice !=
NULL);
23603 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23604 pDevice->aaudio.pStreamCapture =
NULL;
23608 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23609 pDevice->aaudio.pStreamPlayback =
NULL;
23621 ma_assert(pDevice !=
NULL);
23642 pDevice->capture.internalFormat = (((MA_PFN_AAudioStream_getFormat)pContext->aaudio.AAudioStream_getFormat)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture) == MA_AAUDIO_FORMAT_PCM_I16) ?
ma_format_s16 :
ma_format_f32;
23643 pDevice->capture.internalChannels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23644 pDevice->capture.internalSampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23646 pDevice->capture.internalBufferSizeInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pContext->aaudio.AAudioStream_getBufferCapacityInFrames)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23648 framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23649 if (framesPerPeriod > 0) {
23650 pDevice->capture.internalPeriods = pDevice->capture.internalBufferSizeInFrames / framesPerPeriod;
23652 pDevice->capture.internalPeriods = 1;
23664 pDevice->playback.internalFormat = (((MA_PFN_AAudioStream_getFormat)pContext->aaudio.AAudioStream_getFormat)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback) == MA_AAUDIO_FORMAT_PCM_I16) ?
ma_format_s16 :
ma_format_f32;
23665 pDevice->playback.internalChannels = ((MA_PFN_AAudioStream_getChannelCount)pContext->aaudio.AAudioStream_getChannelCount)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23666 pDevice->playback.internalSampleRate = ((MA_PFN_AAudioStream_getSampleRate)pContext->aaudio.AAudioStream_getSampleRate)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23668 pDevice->playback.internalBufferSizeInFrames = ((MA_PFN_AAudioStream_getBufferCapacityInFrames)pContext->aaudio.AAudioStream_getBufferCapacityInFrames)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23670 framesPerPeriod = ((MA_PFN_AAudioStream_getFramesPerDataCallback)pContext->aaudio.AAudioStream_getFramesPerDataCallback)((ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23671 if (framesPerPeriod > 0) {
23672 pDevice->playback.internalPeriods = pDevice->playback.internalBufferSizeInFrames / framesPerPeriod;
23674 pDevice->playback.internalPeriods = 1;
23679 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
23683 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23686 ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23693 ma_uint32 marginSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
23697 ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
23706 ma_result ma_device_start_stream__aaudio(
ma_device* pDevice, ma_AAudioStream* pStream)
23708 ma_aaudio_result_t resultAA;
23709 ma_aaudio_stream_state_t currentState;
23711 ma_assert(pDevice !=
NULL);
23713 resultAA = ((MA_PFN_AAudioStream_requestStart)pDevice->pContext->aaudio.AAudioStream_requestStart)(pStream);
23714 if (resultAA != MA_AAUDIO_OK) {
23715 return ma_result_from_aaudio(resultAA);
23721 currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
23722 if (currentState != MA_AAUDIO_STREAM_STATE_STARTED) {
23725 if (currentState != MA_AAUDIO_STREAM_STATE_STARTING) {
23729 result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STARTED);
23738 ma_result ma_device_stop_stream__aaudio(
ma_device* pDevice, ma_AAudioStream* pStream)
23740 ma_aaudio_result_t resultAA;
23741 ma_aaudio_stream_state_t currentState;
23743 ma_assert(pDevice !=
NULL);
23745 resultAA = ((MA_PFN_AAudioStream_requestStop)pDevice->pContext->aaudio.AAudioStream_requestStop)(pStream);
23746 if (resultAA != MA_AAUDIO_OK) {
23747 return ma_result_from_aaudio(resultAA);
23751 currentState = ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream);
23752 if (currentState != MA_AAUDIO_STREAM_STATE_STOPPED) {
23755 if (currentState != MA_AAUDIO_STREAM_STATE_STOPPING) {
23759 result = ma_wait_for_simple_state_transition__aaudio(pDevice->pContext, pStream, currentState, MA_AAUDIO_STREAM_STATE_STOPPED);
23770 ma_assert(pDevice !=
NULL);
23773 ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23780 ma_result result = ma_device_start_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23783 ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23796 ma_assert(pDevice !=
NULL);
23799 ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
23806 ma_result result = ma_device_stop_stream__aaudio(pDevice, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
23812 onStop = pDevice->onStop;
23823 ma_assert(pContext !=
NULL);
23826 ma_dlclose(pContext, pContext->aaudio.hAAudio);
23827 pContext->aaudio.hAAudio =
NULL;
23834 const char* libNames[] = {
23839 for (i = 0; i < ma_countof(libNames); ++i) {
23840 pContext->aaudio.hAAudio = ma_dlopen(pContext, libNames[i]);
23841 if (pContext->aaudio.hAAudio !=
NULL) {
23846 if (pContext->aaudio.hAAudio ==
NULL) {
23850 pContext->aaudio.AAudio_createStreamBuilder = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudio_createStreamBuilder");
23851 pContext->aaudio.AAudioStreamBuilder_delete = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_delete");
23852 pContext->aaudio.AAudioStreamBuilder_setDeviceId = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setDeviceId");
23853 pContext->aaudio.AAudioStreamBuilder_setDirection = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setDirection");
23854 pContext->aaudio.AAudioStreamBuilder_setSharingMode = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setSharingMode");
23855 pContext->aaudio.AAudioStreamBuilder_setFormat = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setFormat");
23856 pContext->aaudio.AAudioStreamBuilder_setChannelCount = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setChannelCount");
23857 pContext->aaudio.AAudioStreamBuilder_setSampleRate = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setSampleRate");
23858 pContext->aaudio.AAudioStreamBuilder_setBufferCapacityInFrames = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setBufferCapacityInFrames");
23859 pContext->aaudio.AAudioStreamBuilder_setFramesPerDataCallback = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setFramesPerDataCallback");
23860 pContext->aaudio.AAudioStreamBuilder_setDataCallback = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setDataCallback");
23861 pContext->aaudio.AAudioStreamBuilder_setPerformanceMode = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_setPerformanceMode");
23862 pContext->aaudio.AAudioStreamBuilder_openStream = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStreamBuilder_openStream");
23863 pContext->aaudio.AAudioStream_close = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_close");
23864 pContext->aaudio.AAudioStream_getState = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getState");
23865 pContext->aaudio.AAudioStream_waitForStateChange = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_waitForStateChange");
23866 pContext->aaudio.AAudioStream_getFormat = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getFormat");
23867 pContext->aaudio.AAudioStream_getChannelCount = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getChannelCount");
23868 pContext->aaudio.AAudioStream_getSampleRate = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getSampleRate");
23869 pContext->aaudio.AAudioStream_getBufferCapacityInFrames = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getBufferCapacityInFrames");
23870 pContext->aaudio.AAudioStream_getFramesPerDataCallback = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getFramesPerDataCallback");
23871 pContext->aaudio.AAudioStream_getFramesPerBurst = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_getFramesPerBurst");
23872 pContext->aaudio.AAudioStream_requestStart = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_requestStart");
23873 pContext->aaudio.AAudioStream_requestStop = (
ma_proc)ma_dlsym(pContext, pContext->aaudio.hAAudio,
"AAudioStream_requestStop");
23877 pContext->
onUninit = ma_context_uninit__aaudio;
23879 pContext->
onEnumDevices = ma_context_enumerate_devices__aaudio;
23897 #ifdef MA_HAS_OPENSL
23898 #include <SLES/OpenSLES.h>
23900 #include <SLES/OpenSLES_Android.h>
23904 SLObjectItf g_maEngineObjectSL =
NULL;
23905 SLEngineItf g_maEngineSL =
NULL;
23908 #define MA_OPENSL_OBJ(p) (*((SLObjectItf)(p)))
23909 #define MA_OPENSL_OUTPUTMIX(p) (*((SLOutputMixItf)(p)))
23910 #define MA_OPENSL_PLAY(p) (*((SLPlayItf)(p)))
23911 #define MA_OPENSL_RECORD(p) (*((SLRecordItf)(p)))
23914 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLAndroidSimpleBufferQueueItf)(p)))
23916 #define MA_OPENSL_BUFFERQUEUE(p) (*((SLBufferQueueItf)(p)))
23920 ma_uint8 ma_channel_id_to_ma__opensl(SLuint32
id)
23947 SLuint32 ma_channel_id_to_opensl(
ma_uint8 id)
23977 SLuint32 channelMask = 0;
23979 for (iChannel = 0; iChannel < channels; ++iChannel) {
23980 channelMask |= ma_channel_id_to_opensl(channelMap[iChannel]);
23983 return channelMask;
23989 if (channels == 1 && channelMask == 0) {
23991 }
else if (channels == 2 && channelMask == 0) {
23995 if (channels == 1 && (channelMask & SL_SPEAKER_FRONT_CENTER) != 0) {
24001 for (iBit = 0; iBit < 32; ++iBit) {
24002 SLuint32 bitValue = (channelMask & (1UL << iBit));
24003 if (bitValue != 0) {
24005 channelMap[iChannel] = ma_channel_id_to_ma__opensl(bitValue);
24013 SLuint32 ma_round_to_standard_sample_rate__opensl(SLuint32 samplesPerSec)
24015 if (samplesPerSec <= SL_SAMPLINGRATE_8) {
24016 return SL_SAMPLINGRATE_8;
24018 if (samplesPerSec <= SL_SAMPLINGRATE_11_025) {
24019 return SL_SAMPLINGRATE_11_025;
24021 if (samplesPerSec <= SL_SAMPLINGRATE_12) {
24022 return SL_SAMPLINGRATE_12;
24024 if (samplesPerSec <= SL_SAMPLINGRATE_16) {
24025 return SL_SAMPLINGRATE_16;
24027 if (samplesPerSec <= SL_SAMPLINGRATE_22_05) {
24028 return SL_SAMPLINGRATE_22_05;
24030 if (samplesPerSec <= SL_SAMPLINGRATE_24) {
24031 return SL_SAMPLINGRATE_24;
24033 if (samplesPerSec <= SL_SAMPLINGRATE_32) {
24034 return SL_SAMPLINGRATE_32;
24036 if (samplesPerSec <= SL_SAMPLINGRATE_44_1) {
24037 return SL_SAMPLINGRATE_44_1;
24039 if (samplesPerSec <= SL_SAMPLINGRATE_48) {
24040 return SL_SAMPLINGRATE_48;
24045 if (samplesPerSec <= SL_SAMPLINGRATE_64) {
24046 return SL_SAMPLINGRATE_64;
24048 if (samplesPerSec <= SL_SAMPLINGRATE_88_2) {
24049 return SL_SAMPLINGRATE_88_2;
24051 if (samplesPerSec <= SL_SAMPLINGRATE_96) {
24052 return SL_SAMPLINGRATE_96;
24054 if (samplesPerSec <= SL_SAMPLINGRATE_192) {
24055 return SL_SAMPLINGRATE_192;
24059 return SL_SAMPLINGRATE_16;
24065 ma_assert(pContext !=
NULL);
24066 ma_assert(pID0 !=
NULL);
24067 ma_assert(pID1 !=
NULL);
24070 return pID0->opensl == pID1->opensl;
24077 ma_assert(pContext !=
NULL);
24078 ma_assert(callback !=
NULL);
24080 ma_assert(g_maOpenSLInitCounter > 0);
24081 if (g_maOpenSLInitCounter == 0) {
24090 #if 0 && !defined(MA_ANDROID)
24093 SLuint32 pDeviceIDs[128];
24094 SLint32 deviceCount =
sizeof(pDeviceIDs) /
sizeof(pDeviceIDs[0]);
24096 SLAudioIODeviceCapabilitiesItf deviceCaps;
24097 SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
24098 if (resultSL != SL_RESULT_SUCCESS) {
24100 goto return_default_device;
24104 if (!isTerminated) {
24105 resultSL = (*deviceCaps)->GetAvailableAudioOutputs(deviceCaps, &deviceCount, pDeviceIDs);
24106 if (resultSL != SL_RESULT_SUCCESS) {
24110 for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
24112 ma_zero_object(&deviceInfo);
24113 deviceInfo.
id.opensl = pDeviceIDs[iDevice];
24115 SLAudioOutputDescriptor desc;
24116 resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, deviceInfo.
id.opensl, &desc);
24117 if (resultSL == SL_RESULT_SUCCESS) {
24118 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), (
const char*)desc.pDeviceName, (
size_t)-1);
24130 if (!isTerminated) {
24131 resultSL = (*deviceCaps)->GetAvailableAudioInputs(deviceCaps, &deviceCount, pDeviceIDs);
24132 if (resultSL != SL_RESULT_SUCCESS) {
24136 for (SLint32 iDevice = 0; iDevice < deviceCount; ++iDevice) {
24138 ma_zero_object(&deviceInfo);
24139 deviceInfo.
id.opensl = pDeviceIDs[iDevice];
24141 SLAudioInputDescriptor desc;
24142 resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, deviceInfo.
id.opensl, &desc);
24143 if (resultSL == SL_RESULT_SUCCESS) {
24144 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), (
const char*)desc.deviceName, (
size_t)-1);
24157 goto return_default_device;
24160 return_default_device:;
24166 ma_zero_object(&deviceInfo);
24167 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
24174 ma_zero_object(&deviceInfo);
24175 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
24184 ma_assert(pContext !=
NULL);
24186 ma_assert(g_maOpenSLInitCounter > 0);
24187 if (g_maOpenSLInitCounter == 0) {
24201 #if 0 && !defined(MA_ANDROID)
24202 SLAudioIODeviceCapabilitiesItf deviceCaps;
24203 SLresult resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, SL_IID_AUDIOIODEVICECAPABILITIES, &deviceCaps);
24204 if (resultSL != SL_RESULT_SUCCESS) {
24206 goto return_default_device;
24210 SLAudioOutputDescriptor desc;
24211 resultSL = (*deviceCaps)->QueryAudioOutputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
24212 if (resultSL != SL_RESULT_SUCCESS) {
24216 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), (
const char*)desc.pDeviceName, (
size_t)-1);
24218 SLAudioInputDescriptor desc;
24219 resultSL = (*deviceCaps)->QueryAudioInputCapabilities(deviceCaps, pDeviceID->opensl, &desc);
24220 if (resultSL != SL_RESULT_SUCCESS) {
24224 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), (
const char*)desc.deviceName, (
size_t)-1);
24227 goto return_detailed_info;
24229 goto return_default_device;
24232 return_default_device:
24233 if (pDeviceID !=
NULL) {
24242 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
24244 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
24247 goto return_detailed_info;
24250 return_detailed_info:
24264 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24275 void ma_buffer_queue_callback_capture__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue,
void* pUserData)
24278 size_t periodSizeInBytes;
24282 ma_assert(pDevice !=
NULL);
24284 (
void)pBufferQueue;
24293 if (pDevice->state != MA_STATE_STARTED) {
24297 periodSizeInBytes = (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods) * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
24298 pBuffer = pDevice->opensl.pBufferCapture + (pDevice->opensl.currentBufferIndexCapture * periodSizeInBytes);
24301 ma_device__handle_duplex_callback_capture(pDevice, (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods), pBuffer, &pDevice->opensl.duplexRB);
24303 ma_device__send_frames_to_client(pDevice, (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods), pBuffer);
24306 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pBuffer, periodSizeInBytes);
24307 if (resultSL != SL_RESULT_SUCCESS) {
24311 pDevice->opensl.currentBufferIndexCapture = (pDevice->opensl.currentBufferIndexCapture + 1) % pDevice->capture.internalPeriods;
24314 void ma_buffer_queue_callback_playback__opensl_android(SLAndroidSimpleBufferQueueItf pBufferQueue,
void* pUserData)
24317 size_t periodSizeInBytes;
24321 ma_assert(pDevice !=
NULL);
24323 (
void)pBufferQueue;
24326 if (pDevice->state != MA_STATE_STARTED) {
24330 periodSizeInBytes = (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods) * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
24331 pBuffer = pDevice->opensl.pBufferPlayback + (pDevice->opensl.currentBufferIndexPlayback * periodSizeInBytes);
24334 ma_device__handle_duplex_callback_playback(pDevice, (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods), pBuffer, &pDevice->opensl.duplexRB);
24336 ma_device__read_frames_from_client(pDevice, (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods), pBuffer);
24339 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pBuffer, periodSizeInBytes);
24340 if (resultSL != SL_RESULT_SUCCESS) {
24344 pDevice->opensl.currentBufferIndexPlayback = (pDevice->opensl.currentBufferIndexPlayback + 1) % pDevice->playback.internalPeriods;
24348 void ma_device_uninit__opensl(
ma_device* pDevice)
24350 ma_assert(pDevice !=
NULL);
24352 ma_assert(g_maOpenSLInitCounter > 0);
24353 if (g_maOpenSLInitCounter == 0) {
24358 if (pDevice->opensl.pAudioRecorderObj) {
24359 MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioRecorderObj);
24362 ma_free(pDevice->opensl.pBufferCapture);
24366 if (pDevice->opensl.pAudioPlayerObj) {
24367 MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Destroy((SLObjectItf)pDevice->opensl.pAudioPlayerObj);
24369 if (pDevice->opensl.pOutputMixObj) {
24370 MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Destroy((SLObjectItf)pDevice->opensl.pOutputMixObj);
24373 ma_free(pDevice->opensl.pBufferPlayback);
24381 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24382 typedef SLAndroidDataFormat_PCM_EX ma_SLDataFormat_PCM;
24384 typedef SLDataFormat_PCM ma_SLDataFormat_PCM;
24389 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24391 pDataFormat->formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
24392 pDataFormat->representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
24394 pDataFormat->formatType = SL_DATAFORMAT_PCM;
24397 pDataFormat->formatType = SL_DATAFORMAT_PCM;
24400 pDataFormat->numChannels = channels;
24401 ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = ma_round_to_standard_sample_rate__opensl(sampleRate * 1000);
24403 pDataFormat->channelMask = ma_channel_map_to_channel_mask__opensl(channelMap, channels);
24404 pDataFormat->endianness = (ma_is_little_endian()) ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
24413 if (pDataFormat->numChannels > 2) {
24414 pDataFormat->numChannels = 2;
24416 #if __ANDROID_API__ >= 21
24417 if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
24419 ma_assert(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
24420 if (pDataFormat->bitsPerSample > 32) {
24421 pDataFormat->bitsPerSample = 32;
24424 if (pDataFormat->bitsPerSample > 16) {
24425 pDataFormat->bitsPerSample = 16;
24429 if (pDataFormat->bitsPerSample > 16) {
24430 pDataFormat->bitsPerSample = 16;
24433 if (((SLDataFormat_PCM*)pDataFormat)->samplesPerSec > SL_SAMPLINGRATE_48) {
24434 ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec = SL_SAMPLINGRATE_48;
24438 pDataFormat->containerSize = pDataFormat->bitsPerSample;
24446 #if defined(MA_ANDROID) && __ANDROID_API__ >= 21
24447 if (pDataFormat->formatType == SL_ANDROID_DATAFORMAT_PCM_EX) {
24448 ma_assert(pDataFormat->representation == SL_ANDROID_PCM_REPRESENTATION_FLOAT);
24452 if (isFloatingPoint) {
24453 if (pDataFormat->bitsPerSample == 32) {
24457 if (pDataFormat->bitsPerSample == 8) {
24459 }
else if (pDataFormat->bitsPerSample == 16) {
24461 }
else if (pDataFormat->bitsPerSample == 24) {
24463 }
else if (pDataFormat->bitsPerSample == 32) {
24468 *pChannels = pDataFormat->numChannels;
24469 *pSampleRate = ((SLDataFormat_PCM*)pDataFormat)->samplesPerSec / 1000;
24470 ma_channel_mask_to_channel_map__opensl(pDataFormat->channelMask, pDataFormat->numChannels, pChannelMap);
24478 SLDataLocator_AndroidSimpleBufferQueue queue;
24481 size_t bufferSizeInBytes;
24482 const SLInterfaceID itfIDs1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
24483 const SLboolean itfIDsRequired1[] = {SL_BOOLEAN_TRUE};
24488 ma_assert(g_maOpenSLInitCounter > 0);
24489 if (g_maOpenSLInitCounter == 0) {
24510 ma_assert(pDevice !=
NULL);
24511 ma_zero_object(&pDevice->opensl);
24513 queue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
24514 queue.numBuffers = pConfig->
periods;
24518 ma_SLDataFormat_PCM pcm;
24519 SLDataLocator_IODevice locatorDevice;
24525 locatorDevice.locatorType = SL_DATALOCATOR_IODEVICE;
24526 locatorDevice.deviceType = SL_IODEVICE_AUDIOINPUT;
24528 locatorDevice.device =
NULL;
24530 source.pLocator = &locatorDevice;
24533 sink.pLocator = &queue;
24534 sink.pFormat = (SLDataFormat_PCM*)&pcm;
24536 resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &
source, &sink, 1, itfIDs1, itfIDsRequired1);
24537 if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
24539 pcm.formatType = SL_DATAFORMAT_PCM;
24540 pcm.numChannels = 1;
24541 ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16;
24542 pcm.bitsPerSample = 16;
24543 pcm.containerSize = pcm.bitsPerSample;
24544 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
24545 resultSL = (*g_maEngineSL)->CreateAudioRecorder(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioRecorderObj, &
source, &sink, 1, itfIDs1, itfIDsRequired1);
24548 if (resultSL != SL_RESULT_SUCCESS) {
24549 ma_device_uninit__opensl(pDevice);
24553 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->Realize((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
24554 ma_device_uninit__opensl(pDevice);
24558 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_IID_RECORD, &pDevice->opensl.pAudioRecorder) != SL_RESULT_SUCCESS) {
24559 ma_device_uninit__opensl(pDevice);
24563 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioRecorderObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioRecorderObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueueCapture) != SL_RESULT_SUCCESS) {
24564 ma_device_uninit__opensl(pDevice);
24568 if (MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, ma_buffer_queue_callback_capture__opensl_android, pDevice) != SL_RESULT_SUCCESS) {
24569 ma_device_uninit__opensl(pDevice);
24574 ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDevice->capture.internalFormat, &pDevice->capture.internalChannels, &pDevice->capture.internalSampleRate, pDevice->capture.internalChannelMap);
24578 if (bufferSizeInFrames == 0) {
24581 pDevice->capture.internalPeriods = pConfig->
periods;
24582 pDevice->capture.internalBufferSizeInFrames = (bufferSizeInFrames / pDevice->capture.internalPeriods) * pDevice->capture.internalPeriods;
24583 pDevice->opensl.currentBufferIndexCapture = 0;
24585 bufferSizeInBytes = pDevice->capture.internalBufferSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
24587 if (pDevice->opensl.pBufferCapture ==
NULL) {
24588 ma_device_uninit__opensl(pDevice);
24591 MA_ZERO_MEMORY(pDevice->opensl.pBufferCapture, bufferSizeInBytes);
24595 ma_SLDataFormat_PCM pcm;
24597 SLDataLocator_OutputMix outmixLocator;
24602 resultSL = (*g_maEngineSL)->CreateOutputMix(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pOutputMixObj, 0,
NULL,
NULL);
24603 if (resultSL != SL_RESULT_SUCCESS) {
24604 ma_device_uninit__opensl(pDevice);
24608 if (MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->Realize((SLObjectItf)pDevice->opensl.pOutputMixObj, SL_BOOLEAN_FALSE)) {
24609 ma_device_uninit__opensl(pDevice);
24613 if (MA_OPENSL_OBJ(pDevice->opensl.pOutputMixObj)->GetInterface((SLObjectItf)pDevice->opensl.pOutputMixObj, SL_IID_OUTPUTMIX, &pDevice->opensl.pOutputMix) != SL_RESULT_SUCCESS) {
24614 ma_device_uninit__opensl(pDevice);
24621 MA_OPENSL_OUTPUTMIX(pDevice->opensl.pOutputMix)->ReRoute((SLOutputMixItf)pDevice->opensl.pOutputMix, 1, &deviceID_OpenSL);
24624 source.pLocator = &queue;
24625 source.pFormat = (SLDataFormat_PCM*)&pcm;
24627 outmixLocator.locatorType = SL_DATALOCATOR_OUTPUTMIX;
24628 outmixLocator.outputMix = (SLObjectItf)pDevice->opensl.pOutputMixObj;
24630 sink.pLocator = &outmixLocator;
24631 sink.pFormat =
NULL;
24633 resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &
source, &sink, 1, itfIDs1, itfIDsRequired1);
24634 if (resultSL == SL_RESULT_CONTENT_UNSUPPORTED) {
24636 pcm.formatType = SL_DATAFORMAT_PCM;
24637 pcm.numChannels = 2;
24638 ((SLDataFormat_PCM*)&pcm)->samplesPerSec = SL_SAMPLINGRATE_16;
24639 pcm.bitsPerSample = 16;
24640 pcm.containerSize = pcm.bitsPerSample;
24641 pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
24642 resultSL = (*g_maEngineSL)->CreateAudioPlayer(g_maEngineSL, (SLObjectItf*)&pDevice->opensl.pAudioPlayerObj, &
source, &sink, 1, itfIDs1, itfIDsRequired1);
24645 if (resultSL != SL_RESULT_SUCCESS) {
24646 ma_device_uninit__opensl(pDevice);
24650 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->Realize((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
24651 ma_device_uninit__opensl(pDevice);
24655 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_IID_PLAY, &pDevice->opensl.pAudioPlayer) != SL_RESULT_SUCCESS) {
24656 ma_device_uninit__opensl(pDevice);
24660 if (MA_OPENSL_OBJ(pDevice->opensl.pAudioPlayerObj)->GetInterface((SLObjectItf)pDevice->opensl.pAudioPlayerObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &pDevice->opensl.pBufferQueuePlayback) != SL_RESULT_SUCCESS) {
24661 ma_device_uninit__opensl(pDevice);
24665 if (MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->RegisterCallback((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, ma_buffer_queue_callback_playback__opensl_android, pDevice) != SL_RESULT_SUCCESS) {
24666 ma_device_uninit__opensl(pDevice);
24671 ma_deconstruct_SLDataFormat_PCM__opensl(&pcm, &pDevice->playback.internalFormat, &pDevice->playback.internalChannels, &pDevice->playback.internalSampleRate, pDevice->playback.internalChannelMap);
24675 if (bufferSizeInFrames == 0) {
24678 pDevice->playback.internalPeriods = pConfig->
periods;
24679 pDevice->playback.internalBufferSizeInFrames = (bufferSizeInFrames / pDevice->playback.internalPeriods) * pDevice->playback.internalPeriods;
24680 pDevice->opensl.currentBufferIndexPlayback = 0;
24682 bufferSizeInBytes = pDevice->playback.internalBufferSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
24684 if (pDevice->opensl.pBufferPlayback ==
NULL) {
24685 ma_device_uninit__opensl(pDevice);
24688 MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, bufferSizeInBytes);
24692 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames);
24695 ma_device_uninit__opensl(pDevice);
24701 ma_uint32 marginSizeInFrames = rbSizeInFrames / pDevice->capture.internalPeriods;
24705 ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
24720 size_t periodSizeInBytes;
24723 ma_assert(pDevice !=
NULL);
24725 ma_assert(g_maOpenSLInitCounter > 0);
24726 if (g_maOpenSLInitCounter == 0) {
24731 resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_RECORDING);
24732 if (resultSL != SL_RESULT_SUCCESS) {
24736 periodSizeInBytes = (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods) * ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
24737 for (iPeriod = 0; iPeriod < pDevice->capture.internalPeriods; ++iPeriod) {
24738 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture, pDevice->opensl.pBufferCapture + (periodSizeInBytes * iPeriod), periodSizeInBytes);
24739 if (resultSL != SL_RESULT_SUCCESS) {
24740 MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
24747 resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_PLAYING);
24748 if (resultSL != SL_RESULT_SUCCESS) {
24754 MA_ZERO_MEMORY(pDevice->opensl.pBufferPlayback, pDevice->playback.internalBufferSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels));
24756 ma_device__read_frames_from_client(pDevice, pDevice->playback.internalBufferSizeInFrames, pDevice->opensl.pBufferPlayback);
24759 periodSizeInBytes = (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods) * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
24760 for (iPeriod = 0; iPeriod < pDevice->playback.internalPeriods; ++iPeriod) {
24761 resultSL = MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Enqueue((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback, pDevice->opensl.pBufferPlayback + (periodSizeInBytes * iPeriod), periodSizeInBytes);
24762 if (resultSL != SL_RESULT_SUCCESS) {
24763 MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
24777 ma_assert(pDevice !=
NULL);
24779 ma_assert(g_maOpenSLInitCounter > 0);
24780 if (g_maOpenSLInitCounter == 0) {
24787 resultSL = MA_OPENSL_RECORD(pDevice->opensl.pAudioRecorder)->SetRecordState((SLRecordItf)pDevice->opensl.pAudioRecorder, SL_RECORDSTATE_STOPPED);
24788 if (resultSL != SL_RESULT_SUCCESS) {
24792 MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueueCapture)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueueCapture);
24796 resultSL = MA_OPENSL_PLAY(pDevice->opensl.pAudioPlayer)->SetPlayState((SLPlayItf)pDevice->opensl.pAudioPlayer, SL_PLAYSTATE_STOPPED);
24797 if (resultSL != SL_RESULT_SUCCESS) {
24801 MA_OPENSL_BUFFERQUEUE(pDevice->opensl.pBufferQueuePlayback)->Clear((SLAndroidSimpleBufferQueueItf)pDevice->opensl.pBufferQueuePlayback);
24805 onStop = pDevice->onStop;
24816 ma_assert(pContext !=
NULL);
24821 if (g_maOpenSLInitCounter > 0) {
24822 if (ma_atomic_decrement_32(&g_maOpenSLInitCounter) == 0) {
24823 (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
24832 ma_assert(pContext !=
NULL);
24837 if (ma_atomic_increment_32(&g_maOpenSLInitCounter) == 1) {
24838 SLresult resultSL = slCreateEngine(&g_maEngineObjectSL, 0,
NULL, 0,
NULL,
NULL);
24839 if (resultSL != SL_RESULT_SUCCESS) {
24840 ma_atomic_decrement_32(&g_maOpenSLInitCounter);
24844 (*g_maEngineObjectSL)->Realize(g_maEngineObjectSL, SL_BOOLEAN_FALSE);
24846 resultSL = (*g_maEngineObjectSL)->GetInterface(g_maEngineObjectSL, SL_IID_ENGINE, &g_maEngineSL);
24847 if (resultSL != SL_RESULT_SUCCESS) {
24848 (*g_maEngineObjectSL)->Destroy(g_maEngineObjectSL);
24849 ma_atomic_decrement_32(&g_maOpenSLInitCounter);
24856 pContext->
onUninit = ma_context_uninit__opensl;
24858 pContext->
onEnumDevices = ma_context_enumerate_devices__opensl;
24875 #ifdef MA_HAS_WEBAUDIO
24876 #include <emscripten/emscripten.h>
24878 ma_bool32 ma_is_capture_supported__webaudio()
24880 return EM_ASM_INT({
24881 return (navigator.mediaDevices !== undefined && navigator.mediaDevices.getUserMedia !== undefined);
24888 EMSCRIPTEN_KEEPALIVE
void ma_device_process_pcm_frames_capture__webaudio(
ma_device* pDevice,
int frameCount,
float* pFrames)
24891 ma_device__handle_duplex_callback_capture(pDevice, (
ma_uint32)frameCount, pFrames, &pDevice->webaudio.duplexRB);
24893 ma_device__send_frames_to_client(pDevice, (
ma_uint32)frameCount, pFrames);
24897 EMSCRIPTEN_KEEPALIVE
void ma_device_process_pcm_frames_playback__webaudio(
ma_device* pDevice,
int frameCount,
float* pFrames)
24900 ma_device__handle_duplex_callback_playback(pDevice, (
ma_uint32)frameCount, pFrames, &pDevice->webaudio.duplexRB);
24902 ma_device__read_frames_from_client(pDevice, (
ma_uint32)frameCount, pFrames);
24911 ma_assert(pContext !=
NULL);
24912 ma_assert(pID0 !=
NULL);
24913 ma_assert(pID1 !=
NULL);
24916 return ma_strcmp(pID0->webaudio, pID1->webaudio) == 0;
24923 ma_assert(pContext !=
NULL);
24924 ma_assert(callback !=
NULL);
24931 ma_zero_object(&deviceInfo);
24932 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
24938 if (ma_is_capture_supported__webaudio()) {
24940 ma_zero_object(&deviceInfo);
24941 ma_strncpy_s(deviceInfo.
name,
sizeof(deviceInfo.
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
24951 ma_assert(pContext !=
NULL);
24963 ma_zero_memory(pDeviceInfo->
id.webaudio,
sizeof(pDeviceInfo->
id.webaudio));
24967 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (
size_t)-1);
24969 ma_strncpy_s(pDeviceInfo->
name,
sizeof(pDeviceInfo->
name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (
size_t)-1);
24982 var temp =
new (
window.AudioContext ||
window.webkitAudioContext)();
24983 var sampleRate = temp.sampleRate;
25005 ma_assert(pDevice !=
NULL);
25008 var device = miniaudio.get_device_by_index($0);
25011 if (device.scriptNode !== undefined) {
25012 device.scriptNode.onaudioprocess = function(e) {};
25013 device.scriptNode.disconnect();
25014 device.scriptNode = undefined;
25016 if (device.streamNode !== undefined) {
25017 device.streamNode.disconnect();
25018 device.streamNode = undefined;
25025 device.webaudio.close();
25026 device.webaudio = undefined;
25029 if (device.intermediaryBuffer !== undefined) {
25030 Module._free(device.intermediaryBuffer);
25031 device.intermediaryBuffer = undefined;
25032 device.intermediaryBufferView = undefined;
25033 device.intermediaryBufferSizeInBytes = undefined;
25037 miniaudio.untrack_device_by_index($0);
25038 }, deviceIndex, deviceType);
25041 void ma_device_uninit__webaudio(
ma_device* pDevice)
25043 ma_assert(pDevice !=
NULL);
25063 ma_assert(pContext !=
NULL);
25064 ma_assert(pConfig !=
NULL);
25066 ma_assert(pDevice !=
NULL);
25074 if (internalBufferSizeInFrames == 0) {
25079 if (internalBufferSizeInFrames < 256) {
25080 internalBufferSizeInFrames = 256;
25081 }
else if (internalBufferSizeInFrames > 16384) {
25082 internalBufferSizeInFrames = 16384;
25084 internalBufferSizeInFrames = ma_next_power_of_2(internalBufferSizeInFrames);
25088 deviceIndex = EM_ASM_INT({
25090 var sampleRate = $1;
25091 var bufferSize = $2;
25092 var isCapture = $3;
25095 if (typeof(miniaudio) ===
'undefined') {
25102 device.webaudio =
new (
window.AudioContext ||
window.webkitAudioContext)({sampleRate:sampleRate});
25103 device.webaudio.suspend();
25109 device.intermediaryBufferSizeInBytes = channels * bufferSize * 4;
25110 device.intermediaryBuffer = Module._malloc(device.intermediaryBufferSizeInBytes);
25111 device.intermediaryBufferView =
new Float32Array(Module.HEAPF32.buffer, device.intermediaryBuffer, device.intermediaryBufferSizeInBytes);
25129 device.scriptNode = device.webaudio.createScriptProcessor(bufferSize, channels, channels);
25132 device.scriptNode.onaudioprocess =
function(e) {
25133 if (device.intermediaryBuffer === undefined) {
25138 for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
25139 e.outputBuffer.getChannelData(iChannel).fill(0.0);
25143 var sendSilence =
false;
25144 if (device.streamNode === undefined) {
25145 sendSilence =
true;
25149 if (e.inputBuffer.numberOfChannels != channels) {
25150 console.log(
"Capture: Channel count mismatch. " + e.inputBufer.numberOfChannels +
" != " + channels +
". Sending silence.");
25151 sendSilence =
true;
25155 var totalFramesProcessed = 0;
25156 while (totalFramesProcessed < e.inputBuffer.length) {
25157 var framesRemaining = e.inputBuffer.length - totalFramesProcessed;
25158 var framesToProcess = framesRemaining;
25159 if (framesToProcess > (device.intermediaryBufferSizeInBytes/channels/4)) {
25160 framesToProcess = (device.intermediaryBufferSizeInBytes/channels/4);
25165 device.intermediaryBufferView.fill(0.0);
25167 for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
25168 for (var iChannel = 0; iChannel < e.inputBuffer.numberOfChannels; ++iChannel) {
25169 device.intermediaryBufferView[iFrame*channels + iChannel] = e.inputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame];
25175 ccall(
"ma_device_process_pcm_frames_capture__webaudio",
"undefined", [
"number",
"number",
"number"], [pDevice, framesToProcess, device.intermediaryBuffer]);
25177 totalFramesProcessed += framesToProcess;
25181 navigator.mediaDevices.getUserMedia({audio:
true, video:
false})
25182 .then(
function(
stream) {
25183 device.streamNode = device.webaudio.createMediaStreamSource(
stream);
25184 device.streamNode.connect(device.scriptNode);
25185 device.scriptNode.connect(device.webaudio.destination);
25187 .
catch(
function(error) {
25189 device.scriptNode.connect(device.webaudio.destination);
25192 device.scriptNode.onaudioprocess =
function(e) {
25193 if (device.intermediaryBuffer === undefined) {
25197 var outputSilence =
false;
25200 if (e.outputBuffer.numberOfChannels != channels) {
25201 console.log(
"Playback: Channel count mismatch. " + e.outputBufer.numberOfChannels +
" != " + channels +
". Outputting silence.");
25202 outputSilence =
true;
25207 var totalFramesProcessed = 0;
25208 while (totalFramesProcessed < e.outputBuffer.length) {
25209 var framesRemaining = e.outputBuffer.length - totalFramesProcessed;
25210 var framesToProcess = framesRemaining;
25211 if (framesToProcess > (device.intermediaryBufferSizeInBytes/channels/4)) {
25212 framesToProcess = (device.intermediaryBufferSizeInBytes/channels/4);
25216 ccall(
"ma_device_process_pcm_frames_playback__webaudio",
"undefined", [
"number",
"number",
"number"], [pDevice, framesToProcess, device.intermediaryBuffer]);
25219 if (outputSilence) {
25220 for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
25221 e.outputBuffer.getChannelData(iChannel).fill(0.0);
25224 for (var iChannel = 0; iChannel < e.outputBuffer.numberOfChannels; ++iChannel) {
25225 for (var iFrame = 0; iFrame < framesToProcess; ++iFrame) {
25226 e.outputBuffer.getChannelData(iChannel)[totalFramesProcessed + iFrame] = device.intermediaryBufferView[iFrame*channels + iChannel];
25231 totalFramesProcessed += framesToProcess;
25235 device.scriptNode.connect(device.webaudio.destination);
25238 return miniaudio.track_device(device);
25241 if (deviceIndex < 0) {
25246 pDevice->webaudio.indexCapture = deviceIndex;
25250 pDevice->capture.internalSampleRate = EM_ASM_INT({
return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
25251 pDevice->capture.internalBufferSizeInFrames = internalBufferSizeInFrames;
25252 pDevice->capture.internalPeriods = 1;
25254 pDevice->webaudio.indexPlayback = deviceIndex;
25258 pDevice->playback.internalSampleRate = EM_ASM_INT({
return miniaudio.get_device_by_index($0).webaudio.sampleRate; }, deviceIndex);
25259 pDevice->playback.internalBufferSizeInFrames = internalBufferSizeInFrames;
25260 pDevice->playback.internalPeriods = 1;
25303 ma_uint32 rbSizeInFrames = (
ma_uint32)ma_calculate_frame_count_after_src(pDevice->sampleRate, pDevice->capture.internalSampleRate, pDevice->capture.internalBufferSizeInFrames) * 2;
25304 result =
ma_pcm_rb_init(pDevice->capture.format, pDevice->capture.channels, rbSizeInFrames,
NULL, &pDevice->webaudio.duplexRB);
25317 ma_uint32 marginSizeInFrames = rbSizeInFrames / 3;
25321 ma_zero_memory(pMarginData, marginSizeInFrames * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
25332 ma_assert(pDevice !=
NULL);
25336 miniaudio.get_device_by_index($0).webaudio.resume();
25337 }, pDevice->webaudio.indexCapture);
25342 miniaudio.get_device_by_index($0).webaudio.resume();
25343 }, pDevice->webaudio.indexPlayback);
25351 ma_assert(pDevice !=
NULL);
25355 miniaudio.get_device_by_index($0).webaudio.suspend();
25356 }, pDevice->webaudio.indexCapture);
25361 miniaudio.get_device_by_index($0).webaudio.suspend();
25362 }, pDevice->webaudio.indexPlayback);
25375 ma_assert(pContext !=
NULL);
25388 ma_assert(pContext !=
NULL);
25391 resultFromJS = EM_ASM_INT({
25392 if ((
window.AudioContext ||
window.webkitAudioContext) === undefined) {
25396 if (typeof(miniaudio) ===
'undefined') {
25398 miniaudio.devices = [];
25400 miniaudio.track_device =
function(device) {
25402 for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
25403 if (miniaudio.devices[iDevice] ==
null) {
25404 miniaudio.devices[iDevice] = device;
25410 miniaudio.devices.push(device);
25411 return miniaudio.devices.length - 1;
25414 miniaudio.untrack_device_by_index =
function(deviceIndex) {
25416 miniaudio.devices[deviceIndex] =
null;
25419 while (miniaudio.devices.length > 0) {
25420 if (miniaudio.devices[miniaudio.devices.length-1] ==
null) {
25421 miniaudio.devices.pop();
25428 miniaudio.untrack_device =
function(device) {
25429 for (var iDevice = 0; iDevice < miniaudio.devices.length; ++iDevice) {
25430 if (miniaudio.devices[iDevice] == device) {
25431 return miniaudio.untrack_device_by_index(iDevice);
25436 miniaudio.get_device_by_index =
function(deviceIndex) {
25437 return miniaudio.devices[deviceIndex];
25444 if (resultFromJS != 1) {
25451 pContext->
onUninit = ma_context_uninit__webaudio;
25453 pContext->
onEnumDevices = ma_context_enumerate_devices__webaudio;
25473 if (channels == 0) {
25478 for (iChannel = 0; iChannel < channels; ++iChannel) {
25480 for (jChannel = iChannel + 1; jChannel < channels; ++jChannel) {
25481 if (channelMap[iChannel] == channelMap[jChannel]) {
25494 ma_assert(pDevice !=
NULL);
25497 if (pDevice->capture.usingDefaultFormat) {
25498 pDevice->capture.format = pDevice->capture.internalFormat;
25500 if (pDevice->capture.usingDefaultChannels) {
25501 pDevice->capture.channels = pDevice->capture.internalChannels;
25503 if (pDevice->capture.usingDefaultChannelMap) {
25504 if (pDevice->capture.internalChannels == pDevice->capture.channels) {
25505 ma_channel_map_copy(pDevice->capture.channelMap, pDevice->capture.internalChannelMap, pDevice->capture.channels);
25513 if (pDevice->playback.usingDefaultFormat) {
25514 pDevice->playback.format = pDevice->playback.internalFormat;
25516 if (pDevice->playback.usingDefaultChannels) {
25517 pDevice->playback.channels = pDevice->playback.internalChannels;
25519 if (pDevice->playback.usingDefaultChannelMap) {
25520 if (pDevice->playback.internalChannels == pDevice->playback.channels) {
25521 ma_channel_map_copy(pDevice->playback.channelMap, pDevice->playback.internalChannelMap, pDevice->playback.channels);
25528 if (pDevice->usingDefaultSampleRate) {
25530 pDevice->sampleRate = pDevice->capture.internalSampleRate;
25532 pDevice->sampleRate = pDevice->playback.internalSampleRate;
25542 converterConfig.
formatIn = pDevice->capture.internalFormat;
25543 converterConfig.
channelsIn = pDevice->capture.internalChannels;
25544 converterConfig.
sampleRateIn = pDevice->capture.internalSampleRate;
25546 converterConfig.
formatOut = pDevice->capture.format;
25547 converterConfig.
channelsOut = pDevice->capture.channels;
25550 converterConfig.
onRead = ma_device__pcm_converter__on_read_from_buffer_capture;
25559 converterConfig.
formatIn = pDevice->playback.format;
25560 converterConfig.
channelsIn = pDevice->playback.channels;
25563 converterConfig.
formatOut = pDevice->playback.internalFormat;
25564 converterConfig.
channelsOut = pDevice->playback.internalChannels;
25565 converterConfig.
sampleRateOut = pDevice->playback.internalSampleRate;
25569 converterConfig.
onRead = ma_device__on_read_from_client;
25571 converterConfig.
onRead = ma_device__pcm_converter__on_read_from_buffer_playback;
25574 converterConfig.
onRead = ma_device__pcm_converter__on_read_from_buffer_playback;
25581 ma_thread_result MA_THREADCALL ma_worker_thread(
void* pData)
25584 ma_assert(pDevice !=
NULL);
25587 ma_CoInitializeEx(pDevice->pContext,
NULL, MA_COINIT_VALUE);
25596 ma_device__set_state(pDevice, MA_STATE_STOPPED);
25597 ma_event_signal(&pDevice->stopEvent);
25603 ma_event_wait(&pDevice->wakeupEvent);
25609 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED) {
25618 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STARTING);
25621 ma_device__set_state(pDevice, MA_STATE_STARTED);
25622 ma_event_signal(&pDevice->startEvent);
25624 if (pDevice->pContext->onDeviceMainLoop !=
NULL) {
25625 pDevice->pContext->onDeviceMainLoop(pDevice);
25635 if (ma_device__get_state(pDevice) != MA_STATE_UNINITIALIZED) {
25636 if (pDevice->pContext->onDeviceStop) {
25637 pDevice->pContext->onDeviceStop(pDevice);
25642 onStop = pDevice->onStop;
25652 if (ma_device__get_state(pDevice) != MA_STATE_UNINITIALIZED) {
25653 ma_device__set_state(pDevice, MA_STATE_STOPPED);
25654 ma_event_signal(&pDevice->stopEvent);
25659 ma_event_signal(&pDevice->stopEvent);
25662 ma_CoUninitialize(pDevice->pContext);
25665 return (ma_thread_result)0;
25672 if (pDevice ==
NULL) {
25676 return ma_device__get_state(pDevice) != MA_STATE_UNINITIALIZED;
25683 ma_CoUninitialize(pContext);
25684 ma_dlclose(pContext, pContext->win32.hUser32DLL);
25685 ma_dlclose(pContext, pContext->win32.hOle32DLL);
25686 ma_dlclose(pContext, pContext->win32.hAdvapi32DLL);
25693 #ifdef MA_WIN32_DESKTOP
25695 pContext->win32.hOle32DLL = ma_dlopen(pContext,
"ole32.dll");
25696 if (pContext->win32.hOle32DLL ==
NULL) {
25700 pContext->win32.CoInitializeEx = (
ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL,
"CoInitializeEx");
25701 pContext->win32.CoUninitialize = (
ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL,
"CoUninitialize");
25702 pContext->win32.CoCreateInstance = (
ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL,
"CoCreateInstance");
25703 pContext->win32.CoTaskMemFree = (
ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL,
"CoTaskMemFree");
25704 pContext->win32.PropVariantClear = (
ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL,
"PropVariantClear");
25705 pContext->win32.StringFromGUID2 = (
ma_proc)ma_dlsym(pContext, pContext->win32.hOle32DLL,
"StringFromGUID2");
25709 pContext->win32.hUser32DLL = ma_dlopen(pContext,
"user32.dll");
25710 if (pContext->win32.hUser32DLL ==
NULL) {
25714 pContext->win32.GetForegroundWindow = (
ma_proc)ma_dlsym(pContext, pContext->win32.hUser32DLL,
"GetForegroundWindow");
25715 pContext->win32.GetDesktopWindow = (
ma_proc)ma_dlsym(pContext, pContext->win32.hUser32DLL,
"GetDesktopWindow");
25719 pContext->win32.hAdvapi32DLL = ma_dlopen(pContext,
"advapi32.dll");
25720 if (pContext->win32.hAdvapi32DLL ==
NULL) {
25724 pContext->win32.RegOpenKeyExA = (
ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL,
"RegOpenKeyExA");
25725 pContext->win32.RegCloseKey = (
ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL,
"RegCloseKey");
25726 pContext->win32.RegQueryValueExA = (
ma_proc)ma_dlsym(pContext, pContext->win32.hAdvapi32DLL,
"RegQueryValueExA");
25729 ma_CoInitializeEx(pContext,
NULL, MA_COINIT_VALUE);
25735 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
25736 ma_dlclose(pContext, pContext->
posix.pthreadSO);
25747 #if defined(MA_USE_RUNTIME_LINKING_FOR_PTHREAD) && !defined(MA_NO_RUNTIME_LINKING)
25748 const char* libpthreadFileNames[] = {
25755 for (i = 0; i <
sizeof(libpthreadFileNames) /
sizeof(libpthreadFileNames[0]); ++i) {
25756 pContext->
posix.pthreadSO = ma_dlopen(pContext, libpthreadFileNames[i]);
25757 if (pContext->
posix.pthreadSO !=
NULL) {
25762 if (pContext->
posix.pthreadSO ==
NULL) {
25766 pContext->
posix.pthread_create = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_create");
25767 pContext->
posix.pthread_join = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_join");
25768 pContext->
posix.pthread_mutex_init = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_mutex_init");
25769 pContext->
posix.pthread_mutex_destroy = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_mutex_destroy");
25770 pContext->
posix.pthread_mutex_lock = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_mutex_lock");
25771 pContext->
posix.pthread_mutex_unlock = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_mutex_unlock");
25772 pContext->
posix.pthread_cond_init = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_cond_init");
25773 pContext->
posix.pthread_cond_destroy = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_cond_destroy");
25774 pContext->
posix.pthread_cond_wait = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_cond_wait");
25775 pContext->
posix.pthread_cond_signal = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_cond_signal");
25776 pContext->
posix.pthread_attr_init = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_attr_init");
25777 pContext->
posix.pthread_attr_destroy = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_attr_destroy");
25778 pContext->
posix.pthread_attr_setschedpolicy = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_attr_setschedpolicy");
25779 pContext->
posix.pthread_attr_getschedparam = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_attr_getschedparam");
25780 pContext->
posix.pthread_attr_setschedparam = (
ma_proc)ma_dlsym(pContext, pContext->
posix.pthreadSO,
"pthread_attr_setschedparam");
25782 pContext->
posix.pthread_create = (
ma_proc)pthread_create;
25784 pContext->
posix.pthread_mutex_init = (
ma_proc)pthread_mutex_init;
25785 pContext->
posix.pthread_mutex_destroy = (
ma_proc)pthread_mutex_destroy;
25786 pContext->
posix.pthread_mutex_lock = (
ma_proc)pthread_mutex_lock;
25787 pContext->
posix.pthread_mutex_unlock = (
ma_proc)pthread_mutex_unlock;
25788 pContext->
posix.pthread_cond_init = (
ma_proc)pthread_cond_init;
25789 pContext->
posix.pthread_cond_destroy = (
ma_proc)pthread_cond_destroy;
25790 pContext->
posix.pthread_cond_wait = (
ma_proc)pthread_cond_wait;
25791 pContext->
posix.pthread_cond_signal = (
ma_proc)pthread_cond_signal;
25792 pContext->
posix.pthread_attr_init = (
ma_proc)pthread_attr_init;
25793 pContext->
posix.pthread_attr_destroy = (
ma_proc)pthread_attr_destroy;
25794 #if !defined(__EMSCRIPTEN__)
25795 pContext->
posix.pthread_attr_setschedpolicy = (
ma_proc)pthread_attr_setschedpolicy;
25796 pContext->
posix.pthread_attr_getschedparam = (
ma_proc)pthread_attr_getschedparam;
25797 pContext->
posix.pthread_attr_setschedparam = (
ma_proc)pthread_attr_setschedparam;
25809 result = ma_context_init_backend_apis__win32(pContext);
25811 result = ma_context_init_backend_apis__nix(pContext);
25821 result = ma_context_uninit_backend_apis__win32(pContext);
25823 result = ma_context_uninit_backend_apis__nix(pContext);
25844 if (pContext ==
NULL) {
25848 ma_zero_object(pContext);
25851 if (pConfig !=
NULL) {
25862 result = ma_context_init_backend_apis(pContext);
25868 defaultBackends[iBackend] = (
ma_backend)iBackend;
25872 backendsToIterateCount = backendCount;
25873 if (pBackendsToIterate ==
NULL) {
25874 pBackendsToIterate = (
ma_backend*)defaultBackends;
25875 backendsToIterateCount = ma_countof(defaultBackends);
25878 ma_assert(pBackendsToIterate !=
NULL);
25880 for (iBackend = 0; iBackend < backendsToIterateCount; ++iBackend) {
25881 ma_backend backend = pBackendsToIterate[iBackend];
25885 #ifdef MA_HAS_WASAPI
25891 #ifdef MA_HAS_DSOUND
25897 #ifdef MA_HAS_WINMM
25909 #ifdef MA_HAS_PULSEAUDIO
25921 #ifdef MA_HAS_COREAUDIO
25924 result = ma_context_init__coreaudio(&
config, pContext);
25927 #ifdef MA_HAS_SNDIO
25933 #ifdef MA_HAS_AUDIO4
25945 #ifdef MA_HAS_AAUDIO
25951 #ifdef MA_HAS_OPENSL
25957 #ifdef MA_HAS_WEBAUDIO
25960 result = ma_context_init__webaudio(&
config, pContext);
25984 #ifdef MA_DEBUG_OUTPUT
25985 printf(
"[miniaudio] Endian: %s\n", ma_is_little_endian() ?
"LE" :
"BE");
25986 printf(
"[miniaudio] SSE2: %s\n", ma_has_sse2() ?
"YES" :
"NO");
25987 printf(
"[miniaudio] AVX2: %s\n", ma_has_avx2() ?
"YES" :
"NO");
25988 printf(
"[miniaudio] AVX512F: %s\n", ma_has_avx512f() ?
"YES" :
"NO");
25989 printf(
"[miniaudio] NEON: %s\n", ma_has_neon() ?
"YES" :
"NO");
25998 ma_zero_object(pContext);
26004 if (pContext ==
NULL) {
26013 ma_context_uninit_backend_apis(pContext);
26048 const ma_uint32 bufferExpansionCount = 2;
26052 ma_uint32 newCapacity = totalDeviceInfoCount + bufferExpansionCount;
26054 if (pNewInfos ==
NULL) {
26067 size_t iCaptureDevice;
26068 for (iCaptureDevice = totalDeviceInfoCount; iCaptureDevice > iFirstCaptureDevice; --iCaptureDevice) {
26077 pContext->
pDeviceInfos[totalDeviceInfoCount] = *pInfo;
26090 if (ppPlaybackDeviceInfos !=
NULL) *ppPlaybackDeviceInfos =
NULL;
26091 if (pPlaybackDeviceCount !=
NULL) *pPlaybackDeviceCount = 0;
26092 if (ppCaptureDeviceInfos !=
NULL) *ppCaptureDeviceInfos =
NULL;
26093 if (pCaptureDeviceCount !=
NULL) *pCaptureDeviceCount = 0;
26110 if (ppPlaybackDeviceInfos !=
NULL) {
26113 if (pPlaybackDeviceCount !=
NULL) {
26118 if (ppCaptureDeviceInfos !=
NULL) {
26121 if (pCaptureDeviceCount !=
NULL) {
26136 if (pContext ==
NULL || pDeviceInfo ==
NULL) {
26140 ma_zero_object(&deviceInfo);
26143 if (pDeviceID !=
NULL) {
26144 ma_copy_memory(&deviceInfo.
id, pDeviceID,
sizeof(*pDeviceID));
26162 *pDeviceInfo = deviceInfo;
26172 if (pContext ==
NULL) {
26185 if (pContext ==
NULL) {
26188 if (pDevice ==
NULL) {
26191 if (pConfig ==
NULL) {
26207 if (!ma__is_channel_map_valid(
config.capture.channelMap,
config.capture.channels)) {
26216 if (!ma__is_channel_map_valid(
config.playback.channelMap,
config.playback.channels)) {
26222 ma_zero_object(pDevice);
26223 pDevice->pContext = pContext;
26227 pDevice->onData =
config.dataCallback;
26228 pDevice->onStop =
config.stopCallback;
26230 if (((
ma_uintptr)pDevice %
sizeof(pDevice)) != 0) {
26232 pContext->
logCallback(pContext, pDevice,
MA_LOG_LEVEL_WARNING,
"WARNING: ma_device_init() called for a device that is not properly aligned. Thread safety is not supported.");
26236 pDevice->noPreZeroedOutputBuffer =
config.noPreZeroedOutputBuffer;
26237 pDevice->noClip =
config.noClip;
26238 pDevice->masterVolumeFactor = 1;
26244 if (
config.sampleRate == 0) {
26245 config.sampleRate = MA_DEFAULT_SAMPLE_RATE;
26246 pDevice->usingDefaultSampleRate =
MA_TRUE;
26250 config.capture.format = MA_DEFAULT_FORMAT;
26251 pDevice->capture.usingDefaultFormat =
MA_TRUE;
26253 if (
config.capture.channels == 0) {
26254 config.capture.channels = MA_DEFAULT_CHANNELS;
26255 pDevice->capture.usingDefaultChannels =
MA_TRUE;
26258 pDevice->capture.usingDefaultChannelMap =
MA_TRUE;
26262 config.playback.format = MA_DEFAULT_FORMAT;
26263 pDevice->playback.usingDefaultFormat =
MA_TRUE;
26265 if (
config.playback.channels == 0) {
26266 config.playback.channels = MA_DEFAULT_CHANNELS;
26267 pDevice->playback.usingDefaultChannels =
MA_TRUE;
26270 pDevice->playback.usingDefaultChannelMap =
MA_TRUE;
26275 if (
config.bufferSizeInMilliseconds == 0 &&
config.bufferSizeInFrames == 0) {
26277 pDevice->usingDefaultBufferSize =
MA_TRUE;
26281 if (
config.periods == 0) {
26282 config.periods = MA_DEFAULT_PERIODS;
26283 pDevice->usingDefaultPeriods =
MA_TRUE;
26295 pDevice->type =
config.deviceType;
26296 pDevice->sampleRate =
config.sampleRate;
26298 pDevice->capture.shareMode =
config.capture.shareMode;
26299 pDevice->capture.format =
config.capture.format;
26300 pDevice->capture.channels =
config.capture.channels;
26303 pDevice->playback.shareMode =
config.playback.shareMode;
26304 pDevice->playback.format =
config.playback.format;
26305 pDevice->playback.channels =
config.playback.channels;
26310 pDevice->capture.internalFormat = pDevice->capture.format;
26311 pDevice->capture.internalChannels = pDevice->capture.channels;
26312 pDevice->capture.internalSampleRate = pDevice->sampleRate;
26313 ma_channel_map_copy(pDevice->capture.internalChannelMap, pDevice->capture.channelMap, pDevice->capture.channels);
26315 pDevice->playback.internalFormat = pDevice->playback.format;
26316 pDevice->playback.internalChannels = pDevice->playback.channels;
26317 pDevice->playback.internalSampleRate = pDevice->sampleRate;
26318 ma_channel_map_copy(pDevice->playback.internalChannelMap, pDevice->playback.channelMap, pDevice->playback.channels);
26332 if (ma_event_init(pContext, &pDevice->wakeupEvent) !=
MA_SUCCESS) {
26336 if (ma_event_init(pContext, &pDevice->startEvent) !=
MA_SUCCESS) {
26337 ma_event_uninit(&pDevice->wakeupEvent);
26341 if (ma_event_init(pContext, &pDevice->stopEvent) !=
MA_SUCCESS) {
26342 ma_event_uninit(&pDevice->startEvent);
26343 ma_event_uninit(&pDevice->wakeupEvent);
26354 ma_device__post_init_setup(pDevice, pConfig->
deviceType);
26359 if (pDevice->capture.name[0] ==
'\0') {
26361 ma_strncpy_s(pDevice->capture.name,
sizeof(pDevice->capture.name), (
config.capture.pDeviceID ==
NULL) ? MA_DEFAULT_CAPTURE_DEVICE_NAME :
"Capture Device", (
size_t)-1);
26366 if (pDevice->playback.name[0] ==
'\0') {
26368 ma_strncpy_s(pDevice->playback.name,
sizeof(pDevice->playback.name), (
config.playback.pDeviceID ==
NULL) ? MA_DEFAULT_PLAYBACK_DEVICE_NAME :
"Playback Device", (
size_t)-1);
26375 if (!ma_context_is_backend_asynchronous(pContext)) {
26377 if (ma_thread_create(pContext, &pDevice->thread, ma_worker_thread, pDevice) !=
MA_SUCCESS) {
26383 ma_event_wait(&pDevice->stopEvent);
26385 ma_device__set_state(pDevice, MA_STATE_STOPPED);
26389 #ifdef MA_DEBUG_OUTPUT
26392 printf(
" %s (%s)\n", pDevice->capture.name,
"Capture");
26394 printf(
" Channels: %d -> %d\n", pDevice->capture.channels, pDevice->capture.internalChannels);
26395 printf(
" Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->capture.internalSampleRate);
26396 printf(
" Buffer Size: %d/%d (%d)\n", pDevice->capture.internalBufferSizeInFrames, pDevice->capture.internalPeriods, (pDevice->capture.internalBufferSizeInFrames / pDevice->capture.internalPeriods));
26397 printf(
" Conversion:\n");
26398 printf(
" Pre Format Conversion: %s\n", pDevice->capture.converter.isPreFormatConversionRequired ?
"YES" :
"NO");
26399 printf(
" Post Format Conversion: %s\n", pDevice->capture.converter.isPostFormatConversionRequired ?
"YES" :
"NO");
26400 printf(
" Channel Routing: %s\n", pDevice->capture.converter.isChannelRoutingRequired ?
"YES" :
"NO");
26401 printf(
" SRC: %s\n", pDevice->capture.converter.isSRCRequired ?
"YES" :
"NO");
26402 printf(
" Channel Routing at Start: %s\n", pDevice->capture.converter.isChannelRoutingAtStart ?
"YES" :
"NO");
26403 printf(
" Passthrough: %s\n", pDevice->capture.converter.isPassthrough ?
"YES" :
"NO");
26406 printf(
" %s (%s)\n", pDevice->playback.name,
"Playback");
26408 printf(
" Channels: %d -> %d\n", pDevice->playback.channels, pDevice->playback.internalChannels);
26409 printf(
" Sample Rate: %d -> %d\n", pDevice->sampleRate, pDevice->playback.internalSampleRate);
26410 printf(
" Buffer Size: %d/%d (%d)\n", pDevice->playback.internalBufferSizeInFrames, pDevice->playback.internalPeriods, (pDevice->playback.internalBufferSizeInFrames / pDevice->playback.internalPeriods));
26411 printf(
" Conversion:\n");
26412 printf(
" Pre Format Conversion: %s\n", pDevice->playback.converter.isPreFormatConversionRequired ?
"YES" :
"NO");
26413 printf(
" Post Format Conversion: %s\n", pDevice->playback.converter.isPostFormatConversionRequired ?
"YES" :
"NO");
26414 printf(
" Channel Routing: %s\n", pDevice->playback.converter.isChannelRoutingRequired ?
"YES" :
"NO");
26415 printf(
" SRC: %s\n", pDevice->playback.converter.isSRCRequired ?
"YES" :
"NO");
26416 printf(
" Channel Routing at Start: %s\n", pDevice->playback.converter.isChannelRoutingAtStart ?
"YES" :
"NO");
26417 printf(
" Passthrough: %s\n", pDevice->playback.converter.isPassthrough ?
"YES" :
"NO");
26422 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STOPPED);
26435 if (pConfig ==
NULL) {
26440 if (pContext ==
NULL) {
26445 defaultBackends[iBackend] = (
ma_backend)iBackend;
26449 backendsToIterateCount = backendCount;
26450 if (pBackendsToIterate ==
NULL) {
26451 pBackendsToIterate = (
ma_backend*)defaultBackends;
26452 backendsToIterateCount = ma_countof(defaultBackends);
26457 for (iBackend = 0; iBackend < backendsToIterateCount; ++iBackend) {
26474 pDevice->isOwnerOfContext =
MA_TRUE;
26480 if (!ma_device__is_initialized(pDevice)) {
26490 ma_device__set_state(pDevice, MA_STATE_UNINITIALIZED);
26493 if (!ma_context_is_backend_asynchronous(pDevice->pContext)) {
26494 ma_event_signal(&pDevice->wakeupEvent);
26495 ma_thread_wait(&pDevice->thread);
26498 pDevice->pContext->onDeviceUninit(pDevice);
26500 ma_event_uninit(&pDevice->stopEvent);
26501 ma_event_uninit(&pDevice->startEvent);
26502 ma_event_uninit(&pDevice->wakeupEvent);
26505 if (pDevice->isOwnerOfContext) {
26510 ma_zero_object(pDevice);
26515 if (pDevice ==
NULL) {
26519 ma_atomic_exchange_ptr(&pDevice->onStop, proc);
26526 if (pDevice ==
NULL) {
26530 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED) {
26534 if (ma_device__get_state(pDevice) == MA_STATE_STARTED) {
26542 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STOPPED);
26544 ma_device__set_state(pDevice, MA_STATE_STARTING);
26547 if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
26548 result = pDevice->pContext->onDeviceStart(pDevice);
26550 ma_device__set_state(pDevice, MA_STATE_STARTED);
26557 ma_event_signal(&pDevice->wakeupEvent);
26563 ma_event_wait(&pDevice->startEvent);
26564 result = pDevice->workResult;
26576 if (pDevice ==
NULL) {
26580 if (ma_device__get_state(pDevice) == MA_STATE_UNINITIALIZED) {
26584 if (ma_device__get_state(pDevice) == MA_STATE_STOPPED) {
26592 ma_assert(ma_device__get_state(pDevice) == MA_STATE_STARTED);
26594 ma_device__set_state(pDevice, MA_STATE_STOPPING);
26598 if (pDevice->pContext->onDeviceStop) {
26599 result = pDevice->pContext->onDeviceStop(pDevice);
26605 if (ma_context_is_backend_asynchronous(pDevice->pContext)) {
26606 ma_device__set_state(pDevice, MA_STATE_STOPPED);
26614 ma_event_wait(&pDevice->stopEvent);
26625 if (pDevice ==
NULL) {
26629 return ma_device__get_state(pDevice) == MA_STATE_STARTED;
26634 if (pDevice ==
NULL) {
26638 if (volume < 0.0f || volume > 1.0
f) {
26642 pDevice->masterVolumeFactor = volume;
26649 if (pDevice ==
NULL || pVolume ==
NULL) {
26653 *pVolume = pDevice->masterVolumeFactor;
26672 if (pGainDB ==
NULL) {
26690 ma_zero_object(&
config);
26698 ma_zero_object(&
config);
26699 config.deviceType = deviceType;
26731 #ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
26791 if (channels > 8) {
26874 if (channels > 8) {
26933 if (channels > 8) {
27016 if (channels > 8) {
27100 if (channels > 8) {
27183 if (channels > 8) {
27243 if (channels > 6) {
27253 switch (standardChannelMap)
27257 ma_get_standard_channel_map_alsa(channels, channelMap);
27262 ma_get_standard_channel_map_rfc3551(channels, channelMap);
27267 ma_get_standard_channel_map_flac(channels, channelMap);
27272 ma_get_standard_channel_map_vorbis(channels, channelMap);
27277 ma_get_standard_channel_map_sound4(channels, channelMap);
27282 ma_get_standard_channel_map_sndio(channels, channelMap);
27288 ma_get_standard_channel_map_microsoft(channels, channelMap);
27295 if (pOut !=
NULL && pIn !=
NULL && channels > 0) {
27296 ma_copy_memory(pOut, pIn,
sizeof(*pOut) * channels);
27302 if (channelMap ==
NULL) {
27307 if (channels == 0) {
27312 if (channels > 1) {
27314 for (iChannel = 0; iChannel < channels; ++iChannel) {
27328 if (channelMapA == channelMapB) {
27336 for (iChannel = 0; iChannel < channels; ++iChannel) {
27337 if (channelMapA[iChannel] != channelMapB[iChannel]) {
27349 for (iChannel = 0; iChannel < channels; ++iChannel) {
27361 for (iChannel = 0; iChannel < channels; ++iChannel) {
27362 if (channelMap[iChannel] == channelPosition) {
27378 void ma_copy_memory_64(
void*
dst,
const void*
src,
ma_uint64 sizeInBytes)
27380 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
27381 ma_copy_memory(
dst,
src, (
size_t)sizeInBytes);
27383 while (sizeInBytes > 0) {
27384 ma_uint64 bytesToCopyNow = sizeInBytes;
27389 ma_copy_memory(
dst,
src, (
size_t)bytesToCopyNow);
27391 sizeInBytes -= bytesToCopyNow;
27398 void ma_zero_memory_64(
void*
dst,
ma_uint64 sizeInBytes)
27400 #if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
27401 ma_zero_memory(
dst, (
size_t)sizeInBytes);
27403 while (sizeInBytes > 0) {
27404 ma_uint64 bytesToZeroNow = sizeInBytes;
27409 ma_zero_memory(
dst, (
size_t)bytesToZeroNow);
27411 sizeInBytes -= bytesToZeroNow;
27432 for (i = 0; i <
count; i += 1) {
27444 ma_pcm_u8_to_s16__reference(
dst,
src,
count, ditherMode);
27447 #if defined(MA_SUPPORT_SSE2)
27450 ma_pcm_u8_to_s16__optimized(
dst,
src,
count, ditherMode);
27453 #if defined(MA_SUPPORT_AVX2)
27456 ma_pcm_u8_to_s16__optimized(
dst,
src,
count, ditherMode);
27459 #if defined(MA_SUPPORT_AVX512)
27462 ma_pcm_u8_to_s16__avx2(
dst,
src,
count, ditherMode);
27465 #if defined(MA_SUPPORT_NEON)
27468 ma_pcm_u8_to_s16__optimized(
dst,
src,
count, ditherMode);
27474 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27475 ma_pcm_u8_to_s16__reference(
dst,
src,
count, ditherMode);
27477 ma_pcm_u8_to_s16__optimized(
dst,
src,
count, ditherMode);
27488 for (i = 0; i <
count; i += 1) {
27492 dst_s24[i*3+0] = 0;
27493 dst_s24[i*3+1] = 0;
27502 ma_pcm_u8_to_s24__reference(
dst,
src,
count, ditherMode);
27505 #if defined(MA_SUPPORT_SSE2)
27508 ma_pcm_u8_to_s24__optimized(
dst,
src,
count, ditherMode);
27511 #if defined(MA_SUPPORT_AVX2)
27514 ma_pcm_u8_to_s24__optimized(
dst,
src,
count, ditherMode);
27517 #if defined(MA_SUPPORT_AVX512)
27520 ma_pcm_u8_to_s24__avx2(
dst,
src,
count, ditherMode);
27523 #if defined(MA_SUPPORT_NEON)
27526 ma_pcm_u8_to_s24__optimized(
dst,
src,
count, ditherMode);
27532 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27533 ma_pcm_u8_to_s24__reference(
dst,
src,
count, ditherMode);
27535 ma_pcm_u8_to_s24__optimized(
dst,
src,
count, ditherMode);
27546 for (i = 0; i <
count; i += 1) {
27558 ma_pcm_u8_to_s32__reference(
dst,
src,
count, ditherMode);
27561 #if defined(MA_SUPPORT_SSE2)
27564 ma_pcm_u8_to_s32__optimized(
dst,
src,
count, ditherMode);
27567 #if defined(MA_SUPPORT_AVX2)
27570 ma_pcm_u8_to_s32__optimized(
dst,
src,
count, ditherMode);
27573 #if defined(MA_SUPPORT_AVX512)
27576 ma_pcm_u8_to_s32__avx2(
dst,
src,
count, ditherMode);
27579 #if defined(MA_SUPPORT_NEON)
27582 ma_pcm_u8_to_s32__optimized(
dst,
src,
count, ditherMode);
27588 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27589 ma_pcm_u8_to_s32__reference(
dst,
src,
count, ditherMode);
27591 ma_pcm_u8_to_s32__optimized(
dst,
src,
count, ditherMode);
27598 float* dst_f32 = (
float*)
dst;
27602 for (i = 0; i <
count; i += 1) {
27603 float x = (float)src_u8[i];
27604 x =
x * 0.00784313725490196078f;
27615 ma_pcm_u8_to_f32__reference(
dst,
src,
count, ditherMode);
27618 #if defined(MA_SUPPORT_SSE2)
27621 ma_pcm_u8_to_f32__optimized(
dst,
src,
count, ditherMode);
27624 #if defined(MA_SUPPORT_AVX2)
27627 ma_pcm_u8_to_f32__optimized(
dst,
src,
count, ditherMode);
27630 #if defined(MA_SUPPORT_AVX512)
27633 ma_pcm_u8_to_f32__avx2(
dst,
src,
count, ditherMode);
27636 #if defined(MA_SUPPORT_NEON)
27639 ma_pcm_u8_to_f32__optimized(
dst,
src,
count, ditherMode);
27645 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27646 ma_pcm_u8_to_f32__reference(
dst,
src,
count, ditherMode);
27648 ma_pcm_u8_to_f32__optimized(
dst,
src,
count, ditherMode);
27660 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
27662 for (iChannel = 0; iChannel < channels; iChannel += 1) {
27663 dst_u8[iFrame*channels + iChannel] = src_u8[iChannel][iFrame];
27673 if (channels == 1) {
27675 }
else if (channels == 2) {
27677 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
27678 dst_u8[iFrame*2 + 0] = src_u8[0][iFrame];
27679 dst_u8[iFrame*2 + 1] = src_u8[1][iFrame];
27683 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
27685 for (iChannel = 0; iChannel < channels; iChannel += 1) {
27686 dst_u8[iFrame*channels + iChannel] = src_u8[iChannel][iFrame];
27694 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27695 ma_pcm_interleave_u8__reference(
dst,
src, frameCount, channels);
27697 ma_pcm_interleave_u8__optimized(
dst,
src, frameCount, channels);
27708 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
27710 for (iChannel = 0; iChannel < channels; iChannel += 1) {
27711 dst_u8[iChannel][iFrame] = src_u8[iFrame*channels + iChannel];
27718 ma_pcm_deinterleave_u8__reference(
dst,
src, frameCount, channels);
27723 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27724 ma_pcm_deinterleave_u8__reference(
dst,
src, frameCount, channels);
27726 ma_pcm_deinterleave_u8__optimized(
dst,
src, frameCount, channels);
27739 for (i = 0; i <
count; i += 1) {
27747 for (i = 0; i <
count; i += 1) {
27751 ma_int32 dither = ma_dither_s32(ditherMode, -0x80, 0x7F);
27752 if ((
x + dither) <= 0x7FFF) {
27767 ma_pcm_s16_to_u8__reference(
dst,
src,
count, ditherMode);
27770 #if defined(MA_SUPPORT_SSE2)
27773 ma_pcm_s16_to_u8__optimized(
dst,
src,
count, ditherMode);
27776 #if defined(MA_SUPPORT_AVX2)
27779 ma_pcm_s16_to_u8__optimized(
dst,
src,
count, ditherMode);
27782 #if defined(MA_SUPPORT_AVX512)
27785 ma_pcm_s16_to_u8__avx2(
dst,
src,
count, ditherMode);
27788 #if defined(MA_SUPPORT_NEON)
27791 ma_pcm_s16_to_u8__optimized(
dst,
src,
count, ditherMode);
27797 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27798 ma_pcm_s16_to_u8__reference(
dst,
src,
count, ditherMode);
27800 ma_pcm_s16_to_u8__optimized(
dst,
src,
count, ditherMode);
27818 for (i = 0; i <
count; i += 1) {
27819 dst_s24[i*3+0] = 0;
27820 dst_s24[i*3+1] = (
ma_uint8)(src_s16[i] & 0xFF);
27821 dst_s24[i*3+2] = (
ma_uint8)(src_s16[i] >> 8);
27829 ma_pcm_s16_to_s24__reference(
dst,
src,
count, ditherMode);
27832 #if defined(MA_SUPPORT_SSE2)
27835 ma_pcm_s16_to_s24__optimized(
dst,
src,
count, ditherMode);
27838 #if defined(MA_SUPPORT_AVX2)
27841 ma_pcm_s16_to_s24__optimized(
dst,
src,
count, ditherMode);
27844 #if defined(MA_SUPPORT_AVX512)
27847 ma_pcm_s16_to_s24__avx2(
dst,
src,
count, ditherMode);
27850 #if defined(MA_SUPPORT_NEON)
27853 ma_pcm_s16_to_s24__optimized(
dst,
src,
count, ditherMode);
27859 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27860 ma_pcm_s16_to_s24__reference(
dst,
src,
count, ditherMode);
27862 ma_pcm_s16_to_s24__optimized(
dst,
src,
count, ditherMode);
27873 for (i = 0; i <
count; i += 1) {
27874 dst_s32[i] = src_s16[i] << 16;
27882 ma_pcm_s16_to_s32__reference(
dst,
src,
count, ditherMode);
27885 #if defined(MA_SUPPORT_SSE2)
27888 ma_pcm_s16_to_s32__optimized(
dst,
src,
count, ditherMode);
27891 #if defined(MA_SUPPORT_AVX2)
27894 ma_pcm_s16_to_s32__optimized(
dst,
src,
count, ditherMode);
27897 #if defined(MA_SUPPORT_AVX512)
27900 ma_pcm_s16_to_s32__avx2(
dst,
src,
count, ditherMode);
27903 #if defined(MA_SUPPORT_NEON)
27906 ma_pcm_s16_to_s32__optimized(
dst,
src,
count, ditherMode);
27912 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27913 ma_pcm_s16_to_s32__reference(
dst,
src,
count, ditherMode);
27915 ma_pcm_s16_to_s32__optimized(
dst,
src,
count, ditherMode);
27922 float* dst_f32 = (
float*)
dst;
27926 for (i = 0; i <
count; i += 1) {
27927 float x = (float)src_s16[i];
27932 x =
x * 0.00003051804379339284f;
27936 x =
x * 0.000030517578125f;
27947 ma_pcm_s16_to_f32__reference(
dst,
src,
count, ditherMode);
27950 #if defined(MA_SUPPORT_SSE2)
27953 ma_pcm_s16_to_f32__optimized(
dst,
src,
count, ditherMode);
27956 #if defined(MA_SUPPORT_AVX2)
27959 ma_pcm_s16_to_f32__optimized(
dst,
src,
count, ditherMode);
27962 #if defined(MA_SUPPORT_AVX512)
27965 ma_pcm_s16_to_f32__avx2(
dst,
src,
count, ditherMode);
27968 #if defined(MA_SUPPORT_NEON)
27971 ma_pcm_s16_to_f32__optimized(
dst,
src,
count, ditherMode);
27977 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
27978 ma_pcm_s16_to_f32__reference(
dst,
src,
count, ditherMode);
27980 ma_pcm_s16_to_f32__optimized(
dst,
src,
count, ditherMode);
27991 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
27993 for (iChannel = 0; iChannel < channels; iChannel += 1) {
27994 dst_s16[iFrame*channels + iChannel] = src_s16[iChannel][iFrame];
28001 ma_pcm_interleave_s16__reference(
dst,
src, frameCount, channels);
28006 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28007 ma_pcm_interleave_s16__reference(
dst,
src, frameCount, channels);
28009 ma_pcm_interleave_s16__optimized(
dst,
src, frameCount, channels);
28020 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28022 for (iChannel = 0; iChannel < channels; iChannel += 1) {
28023 dst_s16[iChannel][iFrame] = src_s16[iFrame*channels + iChannel];
28030 ma_pcm_deinterleave_s16__reference(
dst,
src, frameCount, channels);
28035 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28036 ma_pcm_deinterleave_s16__reference(
dst,
src, frameCount, channels);
28038 ma_pcm_deinterleave_s16__optimized(
dst,
src, frameCount, channels);
28051 for (i = 0; i <
count; i += 1) {
28057 for (i = 0; i <
count; i += 1) {
28061 ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
28062 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
28077 ma_pcm_s24_to_u8__reference(
dst,
src,
count, ditherMode);
28080 #if defined(MA_SUPPORT_SSE2)
28083 ma_pcm_s24_to_u8__optimized(
dst,
src,
count, ditherMode);
28086 #if defined(MA_SUPPORT_AVX2)
28089 ma_pcm_s24_to_u8__optimized(
dst,
src,
count, ditherMode);
28092 #if defined(MA_SUPPORT_AVX512)
28095 ma_pcm_s24_to_u8__avx2(
dst,
src,
count, ditherMode);
28098 #if defined(MA_SUPPORT_NEON)
28101 ma_pcm_s24_to_u8__optimized(
dst,
src,
count, ditherMode);
28107 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28108 ma_pcm_s24_to_u8__reference(
dst,
src,
count, ditherMode);
28110 ma_pcm_s24_to_u8__optimized(
dst,
src,
count, ditherMode);
28122 for (i = 0; i <
count; i += 1) {
28125 dst_s16[i] = (
ma_int16)dst_lo | dst_hi;
28129 for (i = 0; i <
count; i += 1) {
28133 ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
28134 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
28148 ma_pcm_s24_to_s16__reference(
dst,
src,
count, ditherMode);
28151 #if defined(MA_SUPPORT_SSE2)
28154 ma_pcm_s24_to_s16__optimized(
dst,
src,
count, ditherMode);
28157 #if defined(MA_SUPPORT_AVX2)
28160 ma_pcm_s24_to_s16__optimized(
dst,
src,
count, ditherMode);
28163 #if defined(MA_SUPPORT_AVX512)
28166 ma_pcm_s24_to_s16__avx2(
dst,
src,
count, ditherMode);
28169 #if defined(MA_SUPPORT_NEON)
28172 ma_pcm_s24_to_s16__optimized(
dst,
src,
count, ditherMode);
28178 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28179 ma_pcm_s24_to_s16__reference(
dst,
src,
count, ditherMode);
28181 ma_pcm_s24_to_s16__optimized(
dst,
src,
count, ditherMode);
28200 for (i = 0; i <
count; i += 1) {
28209 ma_pcm_s24_to_s32__reference(
dst,
src,
count, ditherMode);
28212 #if defined(MA_SUPPORT_SSE2)
28215 ma_pcm_s24_to_s32__optimized(
dst,
src,
count, ditherMode);
28218 #if defined(MA_SUPPORT_AVX2)
28221 ma_pcm_s24_to_s32__optimized(
dst,
src,
count, ditherMode);
28224 #if defined(MA_SUPPORT_AVX512)
28227 ma_pcm_s24_to_s32__avx2(
dst,
src,
count, ditherMode);
28230 #if defined(MA_SUPPORT_NEON)
28233 ma_pcm_s24_to_s32__optimized(
dst,
src,
count, ditherMode);
28239 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28240 ma_pcm_s24_to_s32__reference(
dst,
src,
count, ditherMode);
28242 ma_pcm_s24_to_s32__optimized(
dst,
src,
count, ditherMode);
28249 float* dst_f32 = (
float*)
dst;
28253 for (i = 0; i <
count; i += 1) {
28258 x =
x + 8388608.0f;
28259 x =
x * 0.00000011920929665621f;
28263 x =
x * 0.00000011920928955078125f;
28274 ma_pcm_s24_to_f32__reference(
dst,
src,
count, ditherMode);
28277 #if defined(MA_SUPPORT_SSE2)
28280 ma_pcm_s24_to_f32__optimized(
dst,
src,
count, ditherMode);
28283 #if defined(MA_SUPPORT_AVX2)
28286 ma_pcm_s24_to_f32__optimized(
dst,
src,
count, ditherMode);
28289 #if defined(MA_SUPPORT_AVX512)
28292 ma_pcm_s24_to_f32__avx2(
dst,
src,
count, ditherMode);
28295 #if defined(MA_SUPPORT_NEON)
28298 ma_pcm_s24_to_f32__optimized(
dst,
src,
count, ditherMode);
28304 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28305 ma_pcm_s24_to_f32__reference(
dst,
src,
count, ditherMode);
28307 ma_pcm_s24_to_f32__optimized(
dst,
src,
count, ditherMode);
28318 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28320 for (iChannel = 0; iChannel < channels; iChannel += 1) {
28321 dst8[iFrame*3*channels + iChannel*3 + 0] = src8[iChannel][iFrame*3 + 0];
28322 dst8[iFrame*3*channels + iChannel*3 + 1] = src8[iChannel][iFrame*3 + 1];
28323 dst8[iFrame*3*channels + iChannel*3 + 2] = src8[iChannel][iFrame*3 + 2];
28330 ma_pcm_interleave_s24__reference(
dst,
src, frameCount, channels);
28335 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28336 ma_pcm_interleave_s24__reference(
dst,
src, frameCount, channels);
28338 ma_pcm_interleave_s24__optimized(
dst,
src, frameCount, channels);
28349 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28351 for (iChannel = 0; iChannel < channels; iChannel += 1) {
28352 dst8[iChannel][iFrame*3 + 0] = src8[iFrame*3*channels + iChannel*3 + 0];
28353 dst8[iChannel][iFrame*3 + 1] = src8[iFrame*3*channels + iChannel*3 + 1];
28354 dst8[iChannel][iFrame*3 + 2] = src8[iFrame*3*channels + iChannel*3 + 2];
28361 ma_pcm_deinterleave_s24__reference(
dst,
src, frameCount, channels);
28366 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28367 ma_pcm_deinterleave_s24__reference(
dst,
src, frameCount, channels);
28369 ma_pcm_deinterleave_s24__optimized(
dst,
src, frameCount, channels);
28383 for (i = 0; i <
count; i += 1) {
28391 for (i = 0; i <
count; i += 1) {
28395 ma_int32 dither = ma_dither_s32(ditherMode, -0x800000, 0x7FFFFF);
28396 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
28411 ma_pcm_s32_to_u8__reference(
dst,
src,
count, ditherMode);
28414 #if defined(MA_SUPPORT_SSE2)
28417 ma_pcm_s32_to_u8__optimized(
dst,
src,
count, ditherMode);
28420 #if defined(MA_SUPPORT_AVX2)
28423 ma_pcm_s32_to_u8__optimized(
dst,
src,
count, ditherMode);
28426 #if defined(MA_SUPPORT_AVX512)
28429 ma_pcm_s32_to_u8__avx2(
dst,
src,
count, ditherMode);
28432 #if defined(MA_SUPPORT_NEON)
28435 ma_pcm_s32_to_u8__optimized(
dst,
src,
count, ditherMode);
28441 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28442 ma_pcm_s32_to_u8__reference(
dst,
src,
count, ditherMode);
28444 ma_pcm_s32_to_u8__optimized(
dst,
src,
count, ditherMode);
28456 for (i = 0; i <
count; i += 1) {
28463 for (i = 0; i <
count; i += 1) {
28467 ma_int32 dither = ma_dither_s32(ditherMode, -0x8000, 0x7FFF);
28468 if ((
ma_int64)
x + dither <= 0x7FFFFFFF) {
28482 ma_pcm_s32_to_s16__reference(
dst,
src,
count, ditherMode);
28485 #if defined(MA_SUPPORT_SSE2)
28488 ma_pcm_s32_to_s16__optimized(
dst,
src,
count, ditherMode);
28491 #if defined(MA_SUPPORT_AVX2)
28494 ma_pcm_s32_to_s16__optimized(
dst,
src,
count, ditherMode);
28497 #if defined(MA_SUPPORT_AVX512)
28500 ma_pcm_s32_to_s16__avx2(
dst,
src,
count, ditherMode);
28503 #if defined(MA_SUPPORT_NEON)
28506 ma_pcm_s32_to_s16__optimized(
dst,
src,
count, ditherMode);
28512 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28513 ma_pcm_s32_to_s16__reference(
dst,
src,
count, ditherMode);
28515 ma_pcm_s32_to_s16__optimized(
dst,
src,
count, ditherMode);
28526 for (i = 0; i <
count; i += 1) {
28528 dst_s24[i*3+0] = (
ma_uint8)((
x & 0x0000FF00) >> 8);
28529 dst_s24[i*3+1] = (
ma_uint8)((
x & 0x00FF0000) >> 16);
28530 dst_s24[i*3+2] = (
ma_uint8)((
x & 0xFF000000) >> 24);
28538 ma_pcm_s32_to_s24__reference(
dst,
src,
count, ditherMode);
28541 #if defined(MA_SUPPORT_SSE2)
28544 ma_pcm_s32_to_s24__optimized(
dst,
src,
count, ditherMode);
28547 #if defined(MA_SUPPORT_AVX2)
28550 ma_pcm_s32_to_s24__optimized(
dst,
src,
count, ditherMode);
28553 #if defined(MA_SUPPORT_AVX512)
28556 ma_pcm_s32_to_s24__avx2(
dst,
src,
count, ditherMode);
28559 #if defined(MA_SUPPORT_NEON)
28562 ma_pcm_s32_to_s24__optimized(
dst,
src,
count, ditherMode);
28568 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28569 ma_pcm_s32_to_s24__reference(
dst,
src,
count, ditherMode);
28571 ma_pcm_s32_to_s24__optimized(
dst,
src,
count, ditherMode);
28586 float* dst_f32 = (
float*)
dst;
28590 for (i = 0; i <
count; i += 1) {
28591 double x = src_s32[i];
28594 x =
x + 2147483648.0;
28595 x =
x * 0.0000000004656612873077392578125;
28598 x =
x / 2147483648.0;
28601 dst_f32[i] = (float)
x;
28609 ma_pcm_s32_to_f32__reference(
dst,
src,
count, ditherMode);
28612 #if defined(MA_SUPPORT_SSE2)
28615 ma_pcm_s32_to_f32__optimized(
dst,
src,
count, ditherMode);
28618 #if defined(MA_SUPPORT_AVX2)
28621 ma_pcm_s32_to_f32__optimized(
dst,
src,
count, ditherMode);
28624 #if defined(MA_SUPPORT_AVX512)
28627 ma_pcm_s32_to_f32__avx2(
dst,
src,
count, ditherMode);
28630 #if defined(MA_SUPPORT_NEON)
28633 ma_pcm_s32_to_f32__optimized(
dst,
src,
count, ditherMode);
28639 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28640 ma_pcm_s32_to_f32__reference(
dst,
src,
count, ditherMode);
28642 ma_pcm_s32_to_f32__optimized(
dst,
src,
count, ditherMode);
28653 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28655 for (iChannel = 0; iChannel < channels; iChannel += 1) {
28656 dst_s32[iFrame*channels + iChannel] = src_s32[iChannel][iFrame];
28663 ma_pcm_interleave_s32__reference(
dst,
src, frameCount, channels);
28668 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28669 ma_pcm_interleave_s32__reference(
dst,
src, frameCount, channels);
28671 ma_pcm_interleave_s32__optimized(
dst,
src, frameCount, channels);
28682 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
28684 for (iChannel = 0; iChannel < channels; iChannel += 1) {
28685 dst_s32[iChannel][iFrame] = src_s32[iFrame*channels + iChannel];
28692 ma_pcm_deinterleave_s32__reference(
dst,
src, frameCount, channels);
28697 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28698 ma_pcm_deinterleave_s32__reference(
dst,
src, frameCount, channels);
28700 ma_pcm_deinterleave_s32__optimized(
dst,
src, frameCount, channels);
28711 const float* src_f32 = (
const float*)
src;
28713 float ditherMin = 0;
28714 float ditherMax = 0;
28716 ditherMin = 1.0f / -128;
28717 ditherMax = 1.0f / 127;
28720 for (i = 0; i <
count; i += 1) {
28721 float x = src_f32[i];
28722 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
28723 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
28733 ma_pcm_f32_to_u8__reference(
dst,
src,
count, ditherMode);
28736 #if defined(MA_SUPPORT_SSE2)
28739 ma_pcm_f32_to_u8__optimized(
dst,
src,
count, ditherMode);
28742 #if defined(MA_SUPPORT_AVX2)
28745 ma_pcm_f32_to_u8__optimized(
dst,
src,
count, ditherMode);
28748 #if defined(MA_SUPPORT_AVX512)
28751 ma_pcm_f32_to_u8__avx2(
dst,
src,
count, ditherMode);
28754 #if defined(MA_SUPPORT_NEON)
28757 ma_pcm_f32_to_u8__optimized(
dst,
src,
count, ditherMode);
28763 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
28764 ma_pcm_f32_to_u8__reference(
dst,
src,
count, ditherMode);
28766 ma_pcm_f32_to_u8__optimized(
dst,
src,
count, ditherMode);
28776 const float* src_f32 = (
const float*)
src;
28778 float ditherMin = 0;
28779 float ditherMax = 0;
28781 ditherMin = 1.0f / -32768;
28782 ditherMax = 1.0f / 32767;
28785 for (i = 0; i <
count; i += 1) {
28786 float x = src_f32[i];
28787 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
28788 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
28811 const float* src_f32 = (
const float*)
src;
28813 float ditherMin = 0;
28814 float ditherMax = 0;
28816 ditherMin = 1.0f / -32768;
28817 ditherMax = 1.0f / 32767;
28822 count4 =
count >> 2;
28823 for (i4 = 0; i4 < count4; i4 += 1) {
28824 float d0 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
28825 float d1 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
28826 float d2 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
28827 float d3 = ma_dither_f32(ditherMode, ditherMin, ditherMax);
28829 float x0 = src_f32[i+0];
28830 float x1 = src_f32[i+1];
28831 float x2 = src_f32[i+2];
28832 float x3 = src_f32[i+3];
28839 x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
28840 x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
28841 x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
28842 x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
28844 x0 = x0 * 32767.0f;
28845 x1 = x1 * 32767.0f;
28846 x2 = x2 * 32767.0f;
28847 x3 = x3 * 32767.0f;
28858 for (; i <
count; i += 1) {
28859 float x = src_f32[i];
28860 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
28861 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
28868 #if defined(MA_SUPPORT_SSE2)
28875 const float* src_f32;
28881 ma_pcm_f32_to_s16__optimized(
dst,
src,
count, ditherMode);
28886 src_f32 = (
const float*)
src;
28891 ditherMin = 1.0f / -32768;
28892 ditherMax = 1.0f / 32767;
28898 count8 =
count >> 3;
28899 for (i8 = 0; i8 < count8; i8 += 1) {
28906 d0 = _mm_set1_ps(0);
28907 d1 = _mm_set1_ps(0);
28910 ma_dither_f32_rectangle(ditherMin, ditherMax),
28911 ma_dither_f32_rectangle(ditherMin, ditherMax),
28912 ma_dither_f32_rectangle(ditherMin, ditherMax),
28913 ma_dither_f32_rectangle(ditherMin, ditherMax)
28916 ma_dither_f32_rectangle(ditherMin, ditherMax),
28917 ma_dither_f32_rectangle(ditherMin, ditherMax),
28918 ma_dither_f32_rectangle(ditherMin, ditherMax),
28919 ma_dither_f32_rectangle(ditherMin, ditherMax)
28923 ma_dither_f32_triangle(ditherMin, ditherMax),
28924 ma_dither_f32_triangle(ditherMin, ditherMax),
28925 ma_dither_f32_triangle(ditherMin, ditherMax),
28926 ma_dither_f32_triangle(ditherMin, ditherMax)
28929 ma_dither_f32_triangle(ditherMin, ditherMax),
28930 ma_dither_f32_triangle(ditherMin, ditherMax),
28931 ma_dither_f32_triangle(ditherMin, ditherMax),
28932 ma_dither_f32_triangle(ditherMin, ditherMax)
28936 x0 = *((__m128*)(src_f32 + i) + 0);
28937 x1 = *((__m128*)(src_f32 + i) + 1);
28939 x0 = _mm_add_ps(x0, d0);
28940 x1 = _mm_add_ps(x1, d1);
28942 x0 = _mm_mul_ps(x0, _mm_set1_ps(32767.0
f));
28943 x1 = _mm_mul_ps(x1, _mm_set1_ps(32767.0
f));
28945 _mm_stream_si128(((__m128i*)(dst_s16 + i)), _mm_packs_epi32(_mm_cvttps_epi32(x0), _mm_cvttps_epi32(x1)));
28952 for (; i <
count; i += 1) {
28953 float x = src_f32[i];
28954 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
28955 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
28962 #if defined(MA_SUPPORT_AVX2)
28969 const float* src_f32;
28975 ma_pcm_f32_to_s16__optimized(
dst,
src,
count, ditherMode);
28980 src_f32 = (
const float*)
src;
28985 ditherMin = 1.0f / -32768;
28986 ditherMax = 1.0f / 32767;
28992 count16 =
count >> 4;
28993 for (i16 = 0; i16 < count16; i16 += 1) {
29005 d0 = _mm256_set1_ps(0);
29006 d1 = _mm256_set1_ps(0);
29008 d0 = _mm256_set_ps(
29009 ma_dither_f32_rectangle(ditherMin, ditherMax),
29010 ma_dither_f32_rectangle(ditherMin, ditherMax),
29011 ma_dither_f32_rectangle(ditherMin, ditherMax),
29012 ma_dither_f32_rectangle(ditherMin, ditherMax),
29013 ma_dither_f32_rectangle(ditherMin, ditherMax),
29014 ma_dither_f32_rectangle(ditherMin, ditherMax),
29015 ma_dither_f32_rectangle(ditherMin, ditherMax),
29016 ma_dither_f32_rectangle(ditherMin, ditherMax)
29018 d1 = _mm256_set_ps(
29019 ma_dither_f32_rectangle(ditherMin, ditherMax),
29020 ma_dither_f32_rectangle(ditherMin, ditherMax),
29021 ma_dither_f32_rectangle(ditherMin, ditherMax),
29022 ma_dither_f32_rectangle(ditherMin, ditherMax),
29023 ma_dither_f32_rectangle(ditherMin, ditherMax),
29024 ma_dither_f32_rectangle(ditherMin, ditherMax),
29025 ma_dither_f32_rectangle(ditherMin, ditherMax),
29026 ma_dither_f32_rectangle(ditherMin, ditherMax)
29029 d0 = _mm256_set_ps(
29030 ma_dither_f32_triangle(ditherMin, ditherMax),
29031 ma_dither_f32_triangle(ditherMin, ditherMax),
29032 ma_dither_f32_triangle(ditherMin, ditherMax),
29033 ma_dither_f32_triangle(ditherMin, ditherMax),
29034 ma_dither_f32_triangle(ditherMin, ditherMax),
29035 ma_dither_f32_triangle(ditherMin, ditherMax),
29036 ma_dither_f32_triangle(ditherMin, ditherMax),
29037 ma_dither_f32_triangle(ditherMin, ditherMax)
29039 d1 = _mm256_set_ps(
29040 ma_dither_f32_triangle(ditherMin, ditherMax),
29041 ma_dither_f32_triangle(ditherMin, ditherMax),
29042 ma_dither_f32_triangle(ditherMin, ditherMax),
29043 ma_dither_f32_triangle(ditherMin, ditherMax),
29044 ma_dither_f32_triangle(ditherMin, ditherMax),
29045 ma_dither_f32_triangle(ditherMin, ditherMax),
29046 ma_dither_f32_triangle(ditherMin, ditherMax),
29047 ma_dither_f32_triangle(ditherMin, ditherMax)
29051 x0 = *((__m256*)(src_f32 + i) + 0);
29052 x1 = *((__m256*)(src_f32 + i) + 1);
29054 x0 = _mm256_add_ps(x0, d0);
29055 x1 = _mm256_add_ps(x1, d1);
29057 x0 = _mm256_mul_ps(x0, _mm256_set1_ps(32767.0
f));
29058 x1 = _mm256_mul_ps(x1, _mm256_set1_ps(32767.0
f));
29061 i0 = _mm256_cvttps_epi32(x0);
29062 i1 = _mm256_cvttps_epi32(x1);
29063 p0 = _mm256_permute2x128_si256(i0, i1, 0 | 32);
29064 p1 = _mm256_permute2x128_si256(i0, i1, 1 | 48);
29065 r = _mm256_packs_epi32(p0, p1);
29067 _mm256_stream_si256(((__m256i*)(dst_s16 + i)),
r);
29074 for (; i <
count; i += 1) {
29075 float x = src_f32[i];
29076 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29077 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
29084 #if defined(MA_SUPPORT_AVX512)
29088 ma_pcm_f32_to_s16__avx2(
dst,
src,
count, ditherMode);
29091 #if defined(MA_SUPPORT_NEON)
29098 const float* src_f32;
29104 ma_pcm_f32_to_s16__optimized(
dst,
src,
count, ditherMode);
29109 src_f32 = (
const float*)
src;
29114 ditherMin = 1.0f / -32768;
29115 ditherMax = 1.0f / 32767;
29121 count8 =
count >> 3;
29122 for (i8 = 0; i8 < count8; i8 += 1) {
29131 d0 = vmovq_n_f32(0);
29132 d1 = vmovq_n_f32(0);
29135 d0v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29136 d0v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29137 d0v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29138 d0v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29139 d0 = vld1q_f32(d0v);
29142 d1v[0] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29143 d1v[1] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29144 d1v[2] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29145 d1v[3] = ma_dither_f32_rectangle(ditherMin, ditherMax);
29146 d1 = vld1q_f32(d1v);
29149 d0v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
29150 d0v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
29151 d0v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
29152 d0v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
29153 d0 = vld1q_f32(d0v);
29156 d1v[0] = ma_dither_f32_triangle(ditherMin, ditherMax);
29157 d1v[1] = ma_dither_f32_triangle(ditherMin, ditherMax);
29158 d1v[2] = ma_dither_f32_triangle(ditherMin, ditherMax);
29159 d1v[3] = ma_dither_f32_triangle(ditherMin, ditherMax);
29160 d1 = vld1q_f32(d1v);
29163 x0 = *((float32x4_t*)(src_f32 + i) + 0);
29164 x1 = *((float32x4_t*)(src_f32 + i) + 1);
29166 x0 = vaddq_f32(x0, d0);
29167 x1 = vaddq_f32(x1, d1);
29169 x0 = vmulq_n_f32(x0, 32767.0
f);
29170 x1 = vmulq_n_f32(x1, 32767.0
f);
29172 i0 = vcvtq_s32_f32(x0);
29173 i1 = vcvtq_s32_f32(x1);
29174 *((int16x8_t*)(dst_s16 + i)) = vcombine_s16(vqmovn_s32(i0), vqmovn_s32(i1));
29181 for (; i <
count; i += 1) {
29182 float x = src_f32[i];
29183 x =
x + ma_dither_f32(ditherMode, ditherMin, ditherMax);
29184 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
29194 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29195 ma_pcm_f32_to_s16__reference(
dst,
src,
count, ditherMode);
29197 ma_pcm_f32_to_s16__optimized(
dst,
src,
count, ditherMode);
29205 const float* src_f32 = (
const float*)
src;
29208 for (i = 0; i <
count; i += 1) {
29210 float x = src_f32[i];
29211 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
29216 x =
x * 8388607.5f;
29217 x =
x - 8388608.0f;
29220 x =
x * 8388607.0f;
29224 dst_s24[(i*3)+0] = (
ma_uint8)((
r & 0x0000FF) >> 0);
29225 dst_s24[(i*3)+1] = (
ma_uint8)((
r & 0x00FF00) >> 8);
29226 dst_s24[(i*3)+2] = (
ma_uint8)((
r & 0xFF0000) >> 16);
29234 ma_pcm_f32_to_s24__reference(
dst,
src,
count, ditherMode);
29237 #if defined(MA_SUPPORT_SSE2)
29240 ma_pcm_f32_to_s24__optimized(
dst,
src,
count, ditherMode);
29243 #if defined(MA_SUPPORT_AVX2)
29246 ma_pcm_f32_to_s24__optimized(
dst,
src,
count, ditherMode);
29249 #if defined(MA_SUPPORT_AVX512)
29252 ma_pcm_f32_to_s24__avx2(
dst,
src,
count, ditherMode);
29255 #if defined(MA_SUPPORT_NEON)
29258 ma_pcm_f32_to_s24__optimized(
dst,
src,
count, ditherMode);
29264 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29265 ma_pcm_f32_to_s24__reference(
dst,
src,
count, ditherMode);
29267 ma_pcm_f32_to_s24__optimized(
dst,
src,
count, ditherMode);
29275 const float* src_f32 = (
const float*)
src;
29278 for (i = 0; i <
count; i += 1) {
29279 double x = src_f32[i];
29280 x = ((
x < -1) ? -1 : ((
x > 1) ? 1 :
x));
29285 x =
x * 2147483647.5;
29286 x =
x - 2147483648.0;
29289 x =
x * 2147483647.0;
29300 ma_pcm_f32_to_s32__reference(
dst,
src,
count, ditherMode);
29303 #if defined(MA_SUPPORT_SSE2)
29306 ma_pcm_f32_to_s32__optimized(
dst,
src,
count, ditherMode);
29309 #if defined(MA_SUPPORT_AVX2)
29312 ma_pcm_f32_to_s32__optimized(
dst,
src,
count, ditherMode);
29315 #if defined(MA_SUPPORT_AVX512)
29318 ma_pcm_f32_to_s32__avx2(
dst,
src,
count, ditherMode);
29321 #if defined(MA_SUPPORT_NEON)
29324 ma_pcm_f32_to_s32__optimized(
dst,
src,
count, ditherMode);
29330 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29331 ma_pcm_f32_to_s32__reference(
dst,
src,
count, ditherMode);
29333 ma_pcm_f32_to_s32__optimized(
dst,
src,
count, ditherMode);
29342 ma_copy_memory_64(
dst,
src,
count *
sizeof(
float));
29348 float* dst_f32 = (
float*)
dst;
29349 const float** src_f32 = (
const float**)
src;
29352 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
29354 for (iChannel = 0; iChannel < channels; iChannel += 1) {
29355 dst_f32[iFrame*channels + iChannel] = src_f32[iChannel][iFrame];
29362 ma_pcm_interleave_f32__reference(
dst,
src, frameCount, channels);
29367 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29368 ma_pcm_interleave_f32__reference(
dst,
src, frameCount, channels);
29370 ma_pcm_interleave_f32__optimized(
dst,
src, frameCount, channels);
29377 float** dst_f32 = (
float**)
dst;
29378 const float* src_f32 = (
const float*)
src;
29381 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
29383 for (iChannel = 0; iChannel < channels; iChannel += 1) {
29384 dst_f32[iChannel][iFrame] = src_f32[iFrame*channels + iChannel];
29391 ma_pcm_deinterleave_f32__reference(
dst,
src, frameCount, channels);
29396 #ifdef MA_USE_REFERENCE_CONVERSION_APIS
29397 ma_pcm_deinterleave_f32__reference(
dst,
src, frameCount, channels);
29399 ma_pcm_deinterleave_f32__optimized(
dst,
src, frameCount, channels);
29406 ma_assert(pConverter !=
NULL);
29488 #if defined(MA_SUPPORT_SSE2)
29491 ma_assert(pConverter !=
NULL);
29574 #if defined(MA_SUPPORT_AVX2)
29577 ma_assert(pConverter !=
NULL);
29660 #if defined(MA_SUPPORT_AVX512)
29663 ma_assert(pConverter !=
NULL);
29746 #if defined(MA_SUPPORT_NEON)
29749 ma_assert(pConverter !=
NULL);
29834 if (pConverter ==
NULL) {
29837 ma_zero_object(pConverter);
29839 if (pConfig ==
NULL) {
29843 pConverter->
config = *pConfig;
29851 #if defined(MA_SUPPORT_AVX512)
29853 ma_format_converter_init_callbacks__avx512(pConverter);
29856 #if defined(MA_SUPPORT_AVX2)
29858 ma_format_converter_init_callbacks__avx2(pConverter);
29861 #if defined(MA_SUPPORT_SSE2)
29863 ma_format_converter_init_callbacks__sse2(pConverter);
29866 #if defined(MA_SUPPORT_NEON)
29868 ma_format_converter_init_callbacks__neon(pConverter);
29872 ma_format_converter_init_callbacks__default(pConverter);
29916 if (pConverter ==
NULL || pFramesOut ==
NULL) {
29920 totalFramesRead = 0;
29925 pNextFramesOut = (
ma_uint8*)pFramesOut;
29931 while (totalFramesRead < frameCount) {
29933 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
29934 ma_uint64 framesToReadRightNow = framesRemaining;
29935 if (framesToReadRightNow > 0xFFFFFFFF) {
29936 framesToReadRightNow = 0xFFFFFFFF;
29940 if (framesJustRead == 0) {
29944 totalFramesRead += framesJustRead;
29945 pNextFramesOut += framesJustRead * frameSizeOut;
29947 if (framesJustRead < framesToReadRightNow) {
29956 ma_assert(
sizeof(temp) <= 0xFFFFFFFF);
29958 maxFramesToReadAtATime =
sizeof(temp) / sampleSizeIn / pConverter->
config.
channels;
29960 while (totalFramesRead < frameCount) {
29962 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
29963 ma_uint64 framesToReadRightNow = framesRemaining;
29964 if (framesToReadRightNow > maxFramesToReadAtATime) {
29965 framesToReadRightNow = maxFramesToReadAtATime;
29969 if (framesJustRead == 0) {
29975 totalFramesRead += framesJustRead;
29976 pNextFramesOut += framesJustRead * frameSizeOut;
29978 if (framesJustRead < framesToReadRightNow) {
29986 size_t splitBufferSizeOut;
29990 ma_assert(
sizeof(tempSamplesOfOutFormat) <= 0xFFFFFFFF);
29992 ma_split_buffer(tempSamplesOfOutFormat,
sizeof(tempSamplesOfOutFormat), pConverter->
config.
channels,
MA_SIMD_ALIGNMENT, (
void**)&ppTempSamplesOfOutFormat, &splitBufferSizeOut);
29994 maxFramesToReadAtATime = (
ma_uint32)(splitBufferSizeOut / sampleSizeIn);
29996 while (totalFramesRead < frameCount) {
29998 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
29999 ma_uint64 framesToReadRightNow = framesRemaining;
30000 if (framesToReadRightNow > maxFramesToReadAtATime) {
30001 framesToReadRightNow = maxFramesToReadAtATime;
30007 if (framesJustRead == 0) {
30013 size_t splitBufferSizeIn;
30018 ma_split_buffer(tempSamplesOfInFormat,
sizeof(tempSamplesOfInFormat), pConverter->
config.
channels,
MA_SIMD_ALIGNMENT, (
void**)&ppTempSamplesOfInFormat, &splitBufferSizeIn);
30020 if (framesToReadRightNow > (splitBufferSizeIn / sampleSizeIn)) {
30021 framesToReadRightNow = (splitBufferSizeIn / sampleSizeIn);
30025 if (framesJustRead == 0) {
30029 for (iChannel = 0; iChannel < pConverter->
config.
channels; iChannel += 1) {
30030 pConverter->
onConvertPCM(ppTempSamplesOfOutFormat[iChannel], ppTempSamplesOfInFormat[iChannel], framesJustRead, pConverter->
config.
ditherMode);
30036 totalFramesRead += framesJustRead;
30037 pNextFramesOut += framesJustRead * frameSizeOut;
30039 if (framesJustRead < framesToReadRightNow) {
30045 return totalFramesRead;
30055 if (pConverter ==
NULL || ppSamplesOut ==
NULL) {
30059 totalFramesRead = 0;
30063 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
void*) * pConverter->
config.
channels);
30070 ma_assert(
sizeof(tempSamplesOfOutFormat) <= 0xFFFFFFFF);
30072 maxFramesToReadAtATime =
sizeof(tempSamplesOfOutFormat) / sampleSizeIn / pConverter->
config.
channels;
30074 while (totalFramesRead < frameCount) {
30077 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
30078 ma_uint64 framesToReadRightNow = framesRemaining;
30079 if (framesToReadRightNow > maxFramesToReadAtATime) {
30080 framesToReadRightNow = maxFramesToReadAtATime;
30086 if (framesJustRead == 0) {
30094 if (framesJustRead == 0) {
30103 totalFramesRead += framesJustRead;
30104 for (iChannel = 0; iChannel < pConverter->
config.
channels; ++iChannel) {
30105 ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
30108 if (framesJustRead < framesToReadRightNow) {
30116 while (totalFramesRead < frameCount) {
30119 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
30120 ma_uint64 framesToReadRightNow = framesRemaining;
30121 if (framesToReadRightNow > 0xFFFFFFFF) {
30122 framesToReadRightNow = 0xFFFFFFFF;
30126 if (framesJustRead == 0) {
30130 totalFramesRead += framesJustRead;
30131 for (iChannel = 0; iChannel < pConverter->
config.
channels; ++iChannel) {
30132 ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
30135 if (framesJustRead < framesToReadRightNow) {
30142 size_t splitBufferSize;
30146 ma_assert(
sizeof(temp) <= 0xFFFFFFFF);
30150 maxFramesToReadAtATime = (
ma_uint32)(splitBufferSize / sampleSizeIn);
30152 while (totalFramesRead < frameCount) {
30155 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
30156 ma_uint64 framesToReadRightNow = framesRemaining;
30157 if (framesToReadRightNow > maxFramesToReadAtATime) {
30158 framesToReadRightNow = maxFramesToReadAtATime;
30162 if (framesJustRead == 0) {
30166 for (iChannel = 0; iChannel < pConverter->
config.
channels; iChannel += 1) {
30168 ppNextSamplesOut[iChannel] += framesJustRead * sampleSizeOut;
30171 totalFramesRead += framesJustRead;
30173 if (framesJustRead < framesToReadRightNow) {
30180 return totalFramesRead;
30187 ma_zero_object(&
config);
30195 config.formatIn = formatIn;
30196 config.formatOut = formatOut;
30197 config.channels = channels;
30200 config.pUserData = pUserData;
30208 config.onReadDeinterleaved = onReadDeinterleaved;
30233 static MA_INLINE ma_vec3 ma_vec3f(
float x,
float y,
float z)
30243 static MA_INLINE ma_vec3 ma_vec3_add(ma_vec3
a, ma_vec3
b)
30252 static MA_INLINE ma_vec3 ma_vec3_sub(ma_vec3
a, ma_vec3
b)
30261 static MA_INLINE ma_vec3 ma_vec3_mul(ma_vec3
a, ma_vec3
b)
30270 static MA_INLINE ma_vec3 ma_vec3_div(ma_vec3
a, ma_vec3
b)
30279 static MA_INLINE float ma_vec3_dot(ma_vec3
a, ma_vec3
b)
30281 return a.x*
b.x +
a.y*
b.y +
a.z*
b.z;
30284 static MA_INLINE float ma_vec3_length2(ma_vec3
a)
30286 return ma_vec3_dot(
a,
a);
30289 static MA_INLINE float ma_vec3_length(ma_vec3
a)
30291 return (
float)sqrt(ma_vec3_length2(
a));
30294 static MA_INLINE ma_vec3 ma_vec3_normalize(ma_vec3
a)
30296 float len = 1 / ma_vec3_length(
a);
30306 static MA_INLINE float ma_vec3_distance(ma_vec3
a, ma_vec3
b)
30308 return ma_vec3_length(ma_vec3_sub(
a,
b));
30312 #define MA_PLANE_LEFT 0
30313 #define MA_PLANE_RIGHT 1
30314 #define MA_PLANE_FRONT 2
30315 #define MA_PLANE_BACK 3
30316 #define MA_PLANE_BOTTOM 4
30317 #define MA_PLANE_TOP 5
30320 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30321 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30322 { 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f},
30323 { 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f},
30324 { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
30325 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30326 { 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f},
30327 { 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f},
30328 { 0.25f, 0.0f, 0.75f, 0.0f, 0.0f, 0.0f},
30329 { 0.0f, 0.25f, 0.75f, 0.0f, 0.0f, 0.0f},
30330 { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
30331 { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30332 { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30333 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
30334 { 0.33f, 0.0f, 0.33f, 0.0f, 0.0f, 0.34f},
30335 { 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f},
30336 { 0.0f, 0.33f, 0.33f, 0.0f, 0.0f, 0.34f},
30337 { 0.33f, 0.0f, 0.0f, 0.33f, 0.0f, 0.34f},
30338 { 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f},
30339 { 0.0f, 0.33f, 0.0f, 0.33f, 0.0f, 0.34f},
30340 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30341 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30342 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30343 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30344 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30345 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30346 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30347 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30348 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30349 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30350 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30351 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30352 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30353 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30354 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30355 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30356 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30357 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30358 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30359 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30360 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30361 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30362 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30363 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30364 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30365 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30366 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30367 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30368 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30369 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30370 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30371 { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
30374 float ma_calculate_channel_position_planar_weight(
ma_channel channelPositionA,
ma_channel channelPositionB)
30406 float contribution =
30407 g_maChannelPlaneRatios[channelPositionA][0] * g_maChannelPlaneRatios[channelPositionB][0] +
30408 g_maChannelPlaneRatios[channelPositionA][1] * g_maChannelPlaneRatios[channelPositionB][1] +
30409 g_maChannelPlaneRatios[channelPositionA][2] * g_maChannelPlaneRatios[channelPositionB][2] +
30410 g_maChannelPlaneRatios[channelPositionA][3] * g_maChannelPlaneRatios[channelPositionB][3] +
30411 g_maChannelPlaneRatios[channelPositionA][4] * g_maChannelPlaneRatios[channelPositionB][4] +
30412 g_maChannelPlaneRatios[channelPositionA][5] * g_maChannelPlaneRatios[channelPositionB][5];
30414 return contribution;
30419 ma_assert(pRouter !=
NULL);
30422 return ma_calculate_channel_position_planar_weight(channelPositionIn, channelPositionOut);
30429 ma_assert(pRouter !=
NULL);
30436 for (i = 0; i < 6; ++i) {
30437 if (g_maChannelPlaneRatios[channelPosition][i] != 0) {
30450 if (pRouter ==
NULL) {
30454 ma_zero_object(pRouter);
30456 if (pConfig ==
NULL) {
30470 pRouter->
config = *pConfig;
30524 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30526 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30528 isInputChannelPositionInOutput =
MA_TRUE;
30533 if (!isInputChannelPositionInOutput) {
30534 areAllChannelPositionsPresent =
MA_FALSE;
30539 if (areAllChannelPositionsPresent) {
30546 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30547 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30569 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30572 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30575 if (channelPosIn == channelPosOut) {
30585 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30589 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30602 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30611 float monoWeight = 1.0f /
len;
30613 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30617 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30621 pRouter->
config.
weights[iChannelIn][iChannelOut] += monoWeight;
30636 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30639 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosIn)) {
30641 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30644 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosOut)) {
30647 weight = ma_channel_router__calculate_input_channel_planar_weight(pRouter, channelPosIn, channelPosOut);
30651 if (pRouter->
config.
weights[iChannelIn][iChannelOut] == 0) {
30661 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30664 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosOut)) {
30666 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30669 if (ma_channel_router__is_spatial_channel_position(pRouter, channelPosIn)) {
30672 weight = ma_channel_router__calculate_input_channel_planar_weight(pRouter, channelPosIn, channelPosOut);
30676 if (pRouter->
config.
weights[iChannelIn][iChannelOut] == 0) {
30717 void ma_channel_router__do_routing(
ma_channel_router* pRouter,
ma_uint64 frameCount,
float** ppSamplesOut,
const float** ppSamplesIn)
30722 ma_assert(pRouter !=
NULL);
30728 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30730 ma_copy_memory_64(ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn], frameCount *
sizeof(
float));
30736 for (iFrame = 0; iFrame < frameCount; ++iFrame) {
30737 ppSamplesOut[0][iFrame] = ppSamplesIn[0][iFrame];
30738 ppSamplesOut[1][iFrame] = ppSamplesIn[0][iFrame];
30741 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30743 for (iFrame = 0; iFrame < frameCount; ++iFrame) {
30744 ppSamplesOut[iChannelOut][iFrame] = ppSamplesIn[0][iFrame];
30755 for (iFrame = 0; iFrame < frameCount; ++iFrame) {
30756 ppSamplesOut[0][iFrame] = (ppSamplesIn[0][iFrame] + ppSamplesIn[1][iFrame]) * 0.5
f;
30762 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30763 ma_zero_memory_64(ppSamplesOut[iChannelOut], frameCount *
sizeof(
float));
30767 for (iChannelIn = 0; iChannelIn < pRouter->
config.
channelsIn; ++iChannelIn) {
30768 for (iChannelOut = 0; iChannelOut < pRouter->
config.
channelsOut; ++iChannelOut) {
30770 #if defined(MA_SUPPORT_NEON)
30771 if (ma_channel_router__can_use_neon(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
30772 float32x4_t weight = vmovq_n_f32(pRouter->
config.
weights[iChannelIn][iChannelOut]);
30776 for (iFrame4 = 0; iFrame4 < frameCount4; iFrame4 += 1) {
30777 float32x4_t* pO = (float32x4_t*)ppSamplesOut[iChannelOut] + iFrame4;
30778 float32x4_t* pI = (float32x4_t*)ppSamplesIn [iChannelIn ] + iFrame4;
30779 *pO = vaddq_f32(*pO, vmulq_f32(*pI, weight));
30782 iFrame += frameCount4*4;
30786 #if defined(MA_SUPPORT_AVX512)
30787 if (ma_channel_router__can_use_avx512(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
30788 __m512 weight = _mm512_set1_ps(pRouter->
config.
weights[iChannelIn][iChannelOut]);
30789 ma_uint64 frameCount16 = frameCount/16;
30792 for (iFrame16 = 0; iFrame16 < frameCount16; iFrame16 += 1) {
30793 __m512* pO = (__m512*)ppSamplesOut[iChannelOut] + iFrame16;
30794 __m512* pI = (__m512*)ppSamplesIn [iChannelIn ] + iFrame16;
30795 *pO = _mm512_add_ps(*pO, _mm512_mul_ps(*pI, weight));
30798 iFrame += frameCount16*16;
30802 #if defined(MA_SUPPORT_AVX2)
30803 if (ma_channel_router__can_use_avx2(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
30804 __m256 weight = _mm256_set1_ps(pRouter->
config.
weights[iChannelIn][iChannelOut]);
30808 for (iFrame8 = 0; iFrame8 < frameCount8; iFrame8 += 1) {
30809 __m256* pO = (__m256*)ppSamplesOut[iChannelOut] + iFrame8;
30810 __m256* pI = (__m256*)ppSamplesIn [iChannelIn ] + iFrame8;
30811 *pO = _mm256_add_ps(*pO, _mm256_mul_ps(*pI, weight));
30814 iFrame += frameCount8*8;
30818 #if defined(MA_SUPPORT_SSE2)
30819 if (ma_channel_router__can_use_sse2(pRouter, ppSamplesOut[iChannelOut], ppSamplesIn[iChannelIn])) {
30820 __m128 weight = _mm_set1_ps(pRouter->
config.
weights[iChannelIn][iChannelOut]);
30824 for (iFrame4 = 0; iFrame4 < frameCount4; iFrame4 += 1) {
30825 __m128* pO = (__m128*)ppSamplesOut[iChannelOut] + iFrame4;
30826 __m128* pI = (__m128*)ppSamplesIn [iChannelIn ] + iFrame4;
30827 *pO = _mm_add_ps(*pO, _mm_mul_ps(*pI, weight));
30830 iFrame += frameCount4*4;
30834 float weight0 = pRouter->
config.
weights[iChannelIn][iChannelOut];
30835 float weight1 = pRouter->
config.
weights[iChannelIn][iChannelOut];
30836 float weight2 = pRouter->
config.
weights[iChannelIn][iChannelOut];
30837 float weight3 = pRouter->
config.
weights[iChannelIn][iChannelOut];
30841 for (iFrame4 = 0; iFrame4 < frameCount4; iFrame4 += 1) {
30842 ppSamplesOut[iChannelOut][iFrame+0] += ppSamplesIn[iChannelIn][iFrame+0] * weight0;
30843 ppSamplesOut[iChannelOut][iFrame+1] += ppSamplesIn[iChannelIn][iFrame+1] * weight1;
30844 ppSamplesOut[iChannelOut][iFrame+2] += ppSamplesIn[iChannelIn][iFrame+2] * weight2;
30845 ppSamplesOut[iChannelOut][iFrame+3] += ppSamplesIn[iChannelIn][iFrame+3] * weight3;
30851 for (; iFrame < frameCount; ++iFrame) {
30852 ppSamplesOut[iChannelOut][iFrame] += ppSamplesIn[iChannelIn][iFrame] * pRouter->
config.
weights[iChannelIn][iChannelOut];
30861 if (pRouter ==
NULL || ppSamplesOut ==
NULL) {
30867 if (frameCount <= 0xFFFFFFFF) {
30873 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
float*) * pRouter->
config.
channelsOut);
30875 totalFramesRead = 0;
30876 while (totalFramesRead < frameCount) {
30879 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
30880 ma_uint64 framesToReadRightNow = framesRemaining;
30881 if (framesToReadRightNow > 0xFFFFFFFF) {
30882 framesToReadRightNow = 0xFFFFFFFF;
30886 if (framesJustRead == 0) {
30890 totalFramesRead += framesJustRead;
30892 if (framesJustRead < framesToReadRightNow) {
30897 ppNextSamplesOut[iChannel] += framesJustRead;
30901 return totalFramesRead;
30909 size_t maxBytesToReadPerFrameEachIteration;
30910 size_t maxFramesToReadEachIteration;
30914 ma_assert(
sizeof(temp) <= 0xFFFFFFFF);
30915 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
float*) * pRouter->
config.
channelsOut);
30920 maxFramesToReadEachIteration = maxBytesToReadPerFrameEachIteration/
sizeof(float);
30922 totalFramesRead = 0;
30923 while (totalFramesRead < frameCount) {
30926 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
30927 ma_uint64 framesToReadRightNow = framesRemaining;
30928 if (framesToReadRightNow > maxFramesToReadEachIteration) {
30929 framesToReadRightNow = maxFramesToReadEachIteration;
30933 if (framesJustRead == 0) {
30937 ma_channel_router__do_routing(pRouter, framesJustRead, (
float**)ppNextSamplesOut, (
const float**)ppTemp);
30939 totalFramesRead += framesJustRead;
30940 if (totalFramesRead < frameCount) {
30941 for (iChannel = 0; iChannel < pRouter->
config.
channelsIn; iChannel += 1) {
30942 ppNextSamplesOut[iChannel] += framesJustRead;
30946 if (framesJustRead < framesToReadRightNow) {
30951 return totalFramesRead;
30960 ma_zero_object(&
config);
30962 config.channelsIn = channelsIn;
30963 for (iChannel = 0; iChannel < channelsIn; ++iChannel) {
30964 config.channelMapIn[iChannel] = channelMapIn[iChannel];
30967 config.channelsOut = channelsOut;
30968 for (iChannel = 0; iChannel < channelsOut; ++iChannel) {
30969 config.channelMapOut[iChannel] = channelMapOut[iChannel];
30972 config.mixingMode = mixingMode;
30973 config.onReadDeinterleaved = onRead;
30974 config.pUserData = pUserData;
30986 #define ma_floorf(x) ((float)floor((double)(x)))
30987 #define ma_sinf(x) ((float)sin((double)(x)))
30988 #define ma_cosf(x) ((float)cos((double)(x)))
30993 return sin(MA_PI_D*
x) / (MA_PI_D*
x);
30999 #define ma_sincf(x) ((float)ma_sinc((double)(x)))
31002 ma_uint64 ma_src_read_deinterleaved__passthrough(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData);
31003 ma_uint64 ma_src_read_deinterleaved__linear(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData);
31004 ma_uint64 ma_src_read_deinterleaved__sinc(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData);
31006 void ma_src__build_sinc_table__sinc(
ma_src* pSRC)
31010 ma_assert(pSRC !=
NULL);
31012 pSRC->sinc.table[0] = 1.0f;
31013 for (i = 1; i < ma_countof(pSRC->sinc.table); i += 1) {
31015 pSRC->sinc.table[i] = (float)(sin(
x)/
x);
31019 void ma_src__build_sinc_table__rectangular(
ma_src* pSRC)
31022 ma_src__build_sinc_table__sinc(pSRC);
31025 void ma_src__build_sinc_table__hann(
ma_src* pSRC)
31029 ma_src__build_sinc_table__sinc(pSRC);
31031 for (i = 0; i < ma_countof(pSRC->sinc.table); i += 1) {
31032 double x = pSRC->sinc.table[i];
31035 double w = 0.5 * (1 - cos((2*MA_PI_D*n) / (N)));
31037 pSRC->sinc.table[i] = (float)(
x *
w);
31043 if (pSRC ==
NULL) {
31047 ma_zero_object(pSRC);
31056 pSRC->config = *pConfig;
31059 pSRC->useSSE2 = ma_has_sse2() && !pConfig->
noSSE2;
31060 pSRC->useAVX2 = ma_has_avx2() && !pConfig->
noAVX2;
31061 pSRC->useAVX512 = ma_has_avx512f() && !pConfig->
noAVX512;
31062 pSRC->useNEON = ma_has_neon() && !pConfig->
noNEON;
31066 if (pSRC->config.sinc.windowWidth == 0) {
31077 switch (pSRC->config.sinc.windowFunction) {
31089 if (pSRC ==
NULL) {
31094 if (sampleRateIn == 0 || sampleRateOut == 0) {
31098 ma_atomic_exchange_32(&pSRC->config.sampleRateIn, sampleRateIn);
31099 ma_atomic_exchange_32(&pSRC->config.sampleRateOut, sampleRateOut);
31108 if (pSRC ==
NULL || frameCount == 0 || ppSamplesOut ==
NULL) {
31112 algorithm = pSRC->config.algorithm;
31115 switch (algorithm) {
31116 case ma_src_algorithm_none:
return ma_src_read_deinterleaved__passthrough(pSRC, frameCount, ppSamplesOut, pUserData);
31117 case ma_src_algorithm_linear:
return ma_src_read_deinterleaved__linear( pSRC, frameCount, ppSamplesOut, pUserData);
31118 case ma_src_algorithm_sinc:
return ma_src_read_deinterleaved__sinc( pSRC, frameCount, ppSamplesOut, pUserData);
31126 ma_uint64 ma_src_read_deinterleaved__passthrough(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData)
31128 if (frameCount <= 0xFFFFFFFF) {
31129 return pSRC->config.onReadDeinterleaved(pSRC, (
ma_uint32)frameCount, ppSamplesOut, pUserData);
31135 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
31136 ppNextSamplesOut[iChannel] = (
float*)ppSamplesOut[iChannel];
31139 totalFramesRead = 0;
31140 while (totalFramesRead < frameCount) {
31142 ma_uint64 framesRemaining = frameCount - totalFramesRead;
31143 ma_uint64 framesToReadRightNow = framesRemaining;
31144 if (framesToReadRightNow > 0xFFFFFFFF) {
31145 framesToReadRightNow = 0xFFFFFFFF;
31148 framesJustRead = (
ma_uint32)pSRC->config.onReadDeinterleaved(pSRC, (
ma_uint32)framesToReadRightNow, (
void**)ppNextSamplesOut, pUserData);
31149 if (framesJustRead == 0) {
31153 totalFramesRead += framesJustRead;
31154 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
31155 ppNextSamplesOut[iChannel] += framesJustRead;
31158 if (framesJustRead < framesToReadRightNow) {
31163 return totalFramesRead;
31167 ma_uint64 ma_src_read_deinterleaved__linear(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData)
31174 ma_assert(pSRC !=
NULL);
31175 ma_assert(frameCount > 0);
31176 ma_assert(ppSamplesOut !=
NULL);
31178 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
void*) * pSRC->config.channels);
31180 factor = (float)pSRC->config.sampleRateIn / pSRC->config.sampleRateOut;
31181 maxFrameCountPerChunkIn = ma_countof(pSRC->linear.input[0]);
31183 totalFramesRead = 0;
31184 while (totalFramesRead < frameCount) {
31196 ma_uint64 framesRemaining = frameCount - totalFramesRead;
31197 ma_uint64 framesToRead = framesRemaining;
31198 if (framesToRead > 16384) {
31199 framesToRead = 16384;
31204 tBeg = pSRC->linear.timeIn;
31205 tEnd = tBeg + ((
ma_int64)framesToRead*factor);
31207 framesToReadFromClient = (
ma_uint32)(tEnd) + 1 + 1;
31208 if (framesToReadFromClient >= maxFrameCountPerChunkIn) {
31209 framesToReadFromClient = maxFrameCountPerChunkIn;
31212 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
31213 ppSamplesFromClient[iChannel] = pSRC->linear.input[iChannel] + pSRC->linear.leftoverFrames;
31216 framesReadFromClient = 0;
31217 if (framesToReadFromClient > pSRC->linear.leftoverFrames) {
31218 framesReadFromClient = (
ma_uint32)pSRC->config.onReadDeinterleaved(pSRC, (
ma_uint32)framesToReadFromClient - pSRC->linear.leftoverFrames, (
void**)ppSamplesFromClient, pUserData);
31221 framesReadFromClient += pSRC->linear.leftoverFrames;
31222 if (framesReadFromClient < 2) {
31226 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
31227 ppSamplesFromClient[iChannel] = pSRC->linear.input[iChannel];
31237 tAvailable = framesReadFromClient - tBeg - 1;
31239 maxOutputFramesToRead = (
ma_uint32)(tAvailable / factor);
31240 if (maxOutputFramesToRead == 0) {
31241 maxOutputFramesToRead = 1;
31243 if (maxOutputFramesToRead > framesToRead) {
31244 maxOutputFramesToRead = (
ma_uint32)framesToRead;
31248 maxOutputFramesToRead4 = maxOutputFramesToRead/4;
31249 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
31251 float t0 = pSRC->linear.timeIn + factor*0;
31252 float t1 = pSRC->linear.timeIn + factor*1;
31253 float t2 = pSRC->linear.timeIn + factor*2;
31254 float t3 = pSRC->linear.timeIn + factor*3;
31257 for (iFrameOut = 0; iFrameOut < maxOutputFramesToRead4; iFrameOut += 1) {
31258 float iPrevSample0 = (float)floor(t0);
31259 float iPrevSample1 = (float)floor(t1);
31260 float iPrevSample2 = (float)floor(t2);
31261 float iPrevSample3 = (float)floor(t3);
31263 float iNextSample0 = iPrevSample0 + 1;
31264 float iNextSample1 = iPrevSample1 + 1;
31265 float iNextSample2 = iPrevSample2 + 1;
31266 float iNextSample3 = iPrevSample3 + 1;
31268 float alpha0 = t0 - iPrevSample0;
31269 float alpha1 = t1 - iPrevSample1;
31270 float alpha2 = t2 - iPrevSample2;
31271 float alpha3 = t3 - iPrevSample3;
31273 float prevSample0 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample0];
31274 float prevSample1 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample1];
31275 float prevSample2 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample2];
31276 float prevSample3 = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample3];
31278 float nextSample0 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample0];
31279 float nextSample1 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample1];
31280 float nextSample2 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample2];
31281 float nextSample3 = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample3];
31283 ppNextSamplesOut[iChannel][iFrameOut*4 + 0] = ma_mix_f32_fast(prevSample0, nextSample0, alpha0);
31284 ppNextSamplesOut[iChannel][iFrameOut*4 + 1] = ma_mix_f32_fast(prevSample1, nextSample1, alpha1);
31285 ppNextSamplesOut[iChannel][iFrameOut*4 + 2] = ma_mix_f32_fast(prevSample2, nextSample2, alpha2);
31286 ppNextSamplesOut[iChannel][iFrameOut*4 + 3] = ma_mix_f32_fast(prevSample3, nextSample3, alpha3);
31294 t = pSRC->linear.timeIn + (factor*maxOutputFramesToRead4*4);
31295 for (iFrameOut = (maxOutputFramesToRead4*4); iFrameOut < maxOutputFramesToRead; iFrameOut += 1) {
31296 float iPrevSample = (float)floor(t);
31297 float iNextSample = iPrevSample + 1;
31298 float alpha = t - iPrevSample;
31302 ma_assert(iPrevSample < ma_countof(pSRC->linear.input[iChannel]));
31303 ma_assert(iNextSample < ma_countof(pSRC->linear.input[iChannel]));
31305 prevSample = ppSamplesFromClient[iChannel][(
ma_uint32)iPrevSample];
31306 nextSample = ppSamplesFromClient[iChannel][(
ma_uint32)iNextSample];
31308 ppNextSamplesOut[iChannel][iFrameOut] = ma_mix_f32_fast(prevSample, nextSample,
alpha);
31313 ppNextSamplesOut[iChannel] += maxOutputFramesToRead;
31316 totalFramesRead += maxOutputFramesToRead;
31320 tNext = pSRC->linear.timeIn + (maxOutputFramesToRead*factor);
31322 pSRC->linear.timeIn = tNext;
31323 ma_assert(tNext <= framesReadFromClient+1);
31326 pSRC->linear.leftoverFrames = framesReadFromClient - iNextFrame;
31327 pSRC->linear.timeIn = tNext - iNextFrame;
31329 for (iChannel = 0; iChannel < pSRC->config.channels; ++iChannel) {
31331 for (iFrame = 0; iFrame < pSRC->linear.leftoverFrames; ++iFrame) {
31332 float sample = ppSamplesFromClient[iChannel][framesReadFromClient-pSRC->linear.leftoverFrames + iFrame];
31333 ppSamplesFromClient[iChannel][iFrame] =
sample;
31339 if (framesReadFromClient < framesToReadFromClient) {
31344 return totalFramesRead;
31351 ma_zero_object(&
config);
31359 config.sampleRateIn = sampleRateIn;
31360 config.sampleRateOut = sampleRateOut;
31361 config.channels = channels;
31362 config.onReadDeinterleaved = onReadDeinterleaved;
31363 config.pUserData = pUserData;
31397 #define MA_USE_SINC_TABLE_INTERPOLATION
31402 ma_assert(pSRC !=
NULL);
31404 ma_assert(sampleIndex >= -(
ma_int32)pSRC->config.sinc.windowWidth);
31405 ma_assert(sampleIndex < (
ma_int32)pSRC->config.sinc.windowWidth);
31408 ma_assert(windowPosInSamples < ma_countof(pSRC->sinc.input[0]) - pSRC->config.sinc.windowWidth);
31410 return pSRC->sinc.input[
channel][windowPosInSamples + pSRC->config.sinc.windowWidth + sampleIndex];
31413 static MA_INLINE float ma_src_sinc__interpolation_factor(
const ma_src* pSRC,
float x)
31418 ma_assert(pSRC !=
NULL);
31420 xabs = (float)fabs(
x);
31424 #if defined(MA_USE_SINC_TABLE_INTERPOLATION)
31426 float a = xabs - ixabs;
31427 return ma_mix_f32_fast(pSRC->sinc.table[ixabs], pSRC->sinc.table[ixabs+1],
a);
31430 return pSRC->sinc.table[ixabs];
31434 #if defined(MA_SUPPORT_SSE2)
31435 static MA_INLINE __m128 ma_fabsf_sse2(__m128
x)
31437 return _mm_and_ps(_mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF)),
x);
31440 static MA_INLINE __m128 ma_truncf_sse2(__m128
x)
31442 return _mm_cvtepi32_ps(_mm_cvttps_epi32(
x));
31445 static MA_INLINE __m128 ma_src_sinc__interpolation_factor__sse2(
const ma_src* pSRC, __m128
x)
31447 __m128 resolution128;
31457 xabs = ma_fabsf_sse2(
x);
31458 xabs = _mm_mul_ps(xabs, resolution128);
31459 ixabs = _mm_cvttps_epi32(xabs);
31461 ixabsv = (
int*)&ixabs;
31464 pSRC->sinc.table[ixabsv[3]],
31465 pSRC->sinc.table[ixabsv[2]],
31466 pSRC->sinc.table[ixabsv[1]],
31467 pSRC->sinc.table[ixabsv[0]]
31471 pSRC->sinc.table[ixabsv[3]+1],
31472 pSRC->sinc.table[ixabsv[2]+1],
31473 pSRC->sinc.table[ixabsv[1]+1],
31474 pSRC->sinc.table[ixabsv[0]+1]
31477 a = _mm_sub_ps(xabs, _mm_cvtepi32_ps(ixabs));
31478 r = ma_mix_f32_fast__sse2(lo, hi,
a);
31484 #if defined(MA_SUPPORT_AVX2)
31485 static MA_INLINE __m256 ma_fabsf_avx2(__m256
x)
31487 return _mm256_and_ps(_mm256_castsi256_ps(_mm256_set1_epi32(0x7FFFFFFF)),
x);
31491 static MA_INLINE __m256 ma_src_sinc__interpolation_factor__avx2(
const ma_src* pSRC, __m256
x)
31494 __m256 xabs = ma_fabsf_avx2(
x);
31496 xabs = _mm256_mul_ps(xabs, resolution256);
31498 __m256i ixabs = _mm256_cvttps_epi32(xabs);
31499 __m256
a = _mm256_sub_ps(xabs, _mm256_cvtepi32_ps(ixabs));
31502 int* ixabsv = (
int*)&ixabs;
31504 __m256 lo = _mm256_set_ps(
31505 pSRC->sinc.table[ixabsv[7]],
31506 pSRC->sinc.table[ixabsv[6]],
31507 pSRC->sinc.table[ixabsv[5]],
31508 pSRC->sinc.table[ixabsv[4]],
31509 pSRC->sinc.table[ixabsv[3]],
31510 pSRC->sinc.table[ixabsv[2]],
31511 pSRC->sinc.table[ixabsv[1]],
31512 pSRC->sinc.table[ixabsv[0]]
31515 __m256 hi = _mm256_set_ps(
31516 pSRC->sinc.table[ixabsv[7]+1],
31517 pSRC->sinc.table[ixabsv[6]+1],
31518 pSRC->sinc.table[ixabsv[5]+1],
31519 pSRC->sinc.table[ixabsv[4]+1],
31520 pSRC->sinc.table[ixabsv[3]+1],
31521 pSRC->sinc.table[ixabsv[2]+1],
31522 pSRC->sinc.table[ixabsv[1]+1],
31523 pSRC->sinc.table[ixabsv[0]+1]
31526 __m256
r = ma_mix_f32_fast__avx2(lo, hi,
a);
31534 #if defined(MA_SUPPORT_NEON)
31535 static MA_INLINE float32x4_t ma_fabsf_neon(float32x4_t
x)
31537 return vabdq_f32(vmovq_n_f32(0),
x);
31540 static MA_INLINE float32x4_t ma_src_sinc__interpolation_factor__neon(
const ma_src* pSRC, float32x4_t
x)
31550 xabs = ma_fabsf_neon(
x);
31552 ixabs = vcvtq_s32_f32(xabs);
31554 ixabsv = (
int*)&ixabs;
31556 lo[0] = pSRC->sinc.table[ixabsv[0]];
31557 lo[1] = pSRC->sinc.table[ixabsv[1]];
31558 lo[2] = pSRC->sinc.table[ixabsv[2]];
31559 lo[3] = pSRC->sinc.table[ixabsv[3]];
31561 hi[0] = pSRC->sinc.table[ixabsv[0]+1];
31562 hi[1] = pSRC->sinc.table[ixabsv[1]+1];
31563 hi[2] = pSRC->sinc.table[ixabsv[2]+1];
31564 hi[3] = pSRC->sinc.table[ixabsv[3]+1];
31566 a = vsubq_f32(xabs, vcvtq_f32_s32(ixabs));
31567 r = ma_mix_f32_fast__neon(vld1q_f32(lo), vld1q_f32(hi),
a);
31573 ma_uint64 ma_src_read_deinterleaved__sinc(
ma_src* pSRC,
ma_uint64 frameCount,
void** ppSamplesOut,
void* pUserData)
31576 float inverseFactor;
31583 float* windowSamples;
31589 ma_assert(pSRC !=
NULL);
31590 ma_assert(frameCount > 0);
31591 ma_assert(ppSamplesOut !=
NULL);
31593 factor = (float)pSRC->config.sampleRateIn / pSRC->config.sampleRateOut;
31594 inverseFactor = 1/factor;
31596 windowWidth = (
ma_int32)pSRC->config.sinc.windowWidth;
31597 windowWidth2 = windowWidth*2;
31603 windowWidthSIMD = windowWidth;
31604 if (pSRC->useNEON) {
31605 windowWidthSIMD = (windowWidthSIMD + 1) & ~(1);
31606 }
else if (pSRC->useAVX512) {
31607 windowWidthSIMD = (windowWidthSIMD + 7) & ~(7);
31608 }
else if (pSRC->useAVX2) {
31609 windowWidthSIMD = (windowWidthSIMD + 3) & ~(3);
31610 }
else if (pSRC->useSSE2) {
31611 windowWidthSIMD = (windowWidthSIMD + 1) & ~(1);
31614 windowWidthSIMD2 = windowWidthSIMD*2;
31615 (
void)windowWidthSIMD2;
31617 ma_copy_memory(ppNextSamplesOut, ppSamplesOut,
sizeof(
void*) * pSRC->config.channels);
31625 for (i = 0; i < windowWidth2; ++i) {
31626 iWindowF[i] = (float)(i - windowWidth);
31629 totalOutputFramesRead = 0;
31630 while (totalOutputFramesRead < frameCount) {
31631 ma_uint32 maxInputSamplesAvailableInCache;
31645 maxInputSamplesAvailableInCache = ma_countof(pSRC->sinc.input[0]) - (pSRC->config.sinc.windowWidth*2) - pSRC->sinc.windowPosInSamples;
31646 if (maxInputSamplesAvailableInCache > pSRC->sinc.inputFrameCount) {
31647 maxInputSamplesAvailableInCache = pSRC->sinc.inputFrameCount;
31651 if (pSRC->config.neverConsumeEndOfInput) {
31652 if (maxInputSamplesAvailableInCache >= pSRC->config.sinc.windowWidth) {
31653 maxInputSamplesAvailableInCache -= pSRC->config.sinc.windowWidth;
31655 maxInputSamplesAvailableInCache = 0;
31659 timeInBeg = pSRC->sinc.timeIn;
31660 timeInEnd = (float)(pSRC->sinc.windowPosInSamples + maxInputSamplesAvailableInCache);
31662 ma_assert(timeInBeg >= 0);
31663 ma_assert(timeInBeg <= timeInEnd);
31665 maxOutputFramesToRead = (
ma_uint64)(((timeInEnd - timeInBeg) * inverseFactor));
31667 outputFramesRemaining = frameCount - totalOutputFramesRead;
31668 outputFramesToRead = outputFramesRemaining;
31669 if (outputFramesToRead > maxOutputFramesToRead) {
31670 outputFramesToRead = maxOutputFramesToRead;
31673 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
31675 float timeIn = timeInBeg;
31677 for (iSample = 0; iSample < outputFramesToRead; iSample += 1) {
31678 float sampleOut = 0;
31679 float iTimeInF = ma_floorf(timeIn);
31685 windowSamples[0] = 0;
31686 for (i = 1; i < windowWidth2; ++i) {
31687 windowSamples[i] = pSRC->sinc.input[iChannel][iTimeIn + i];
31690 #if defined(MA_SUPPORT_AVX2) || defined(MA_SUPPORT_AVX512)
31691 if (pSRC->useAVX2 || pSRC->useAVX512) {
31694 __m256 resolution256;
31702 t = _mm256_set1_ps((timeIn - iTimeInF));
31703 r = _mm256_set1_ps(0);
31705 windowWidth8 = windowWidthSIMD2 >> 3;
31706 for (iWindow8 = 0; iWindow8 < windowWidth8; iWindow8 += 1) {
31707 __m256
w = *((__m256*)iWindowF + iWindow8);
31709 __m256 xabs = _mm256_sub_ps(t,
w);
31710 xabs = ma_fabsf_avx2(xabs);
31711 xabs = _mm256_mul_ps(xabs, resolution256);
31713 ixabs[iWindow8] = _mm256_cvttps_epi32(xabs);
31714 a[iWindow8] = _mm256_sub_ps(xabs, _mm256_cvtepi32_ps(ixabs[iWindow8]));
31717 for (iWindow8 = 0; iWindow8 < windowWidth8; iWindow8 += 1) {
31718 int* ixabsv = (
int*)&ixabs[iWindow8];
31720 __m256 lo = _mm256_set_ps(
31721 pSRC->sinc.table[ixabsv[7]],
31722 pSRC->sinc.table[ixabsv[6]],
31723 pSRC->sinc.table[ixabsv[5]],
31724 pSRC->sinc.table[ixabsv[4]],
31725 pSRC->sinc.table[ixabsv[3]],
31726 pSRC->sinc.table[ixabsv[2]],
31727 pSRC->sinc.table[ixabsv[1]],
31728 pSRC->sinc.table[ixabsv[0]]
31731 __m256 hi = _mm256_set_ps(
31732 pSRC->sinc.table[ixabsv[7]+1],
31733 pSRC->sinc.table[ixabsv[6]+1],
31734 pSRC->sinc.table[ixabsv[5]+1],
31735 pSRC->sinc.table[ixabsv[4]+1],
31736 pSRC->sinc.table[ixabsv[3]+1],
31737 pSRC->sinc.table[ixabsv[2]+1],
31738 pSRC->sinc.table[ixabsv[1]+1],
31739 pSRC->sinc.table[ixabsv[0]+1]
31742 __m256 s = *((__m256*)windowSamples + iWindow8);
31743 r = _mm256_add_ps(
r, _mm256_mul_ps(s, ma_mix_f32_fast__avx2(lo, hi,
a[iWindow8])));
31747 __m256
x = _mm256_hadd_ps(
r, _mm256_permute2f128_ps(
r,
r, 1));
31748 x = _mm256_hadd_ps(
x,
x);
31749 x = _mm256_hadd_ps(
x,
x);
31750 sampleOut += _mm_cvtss_f32(_mm256_castps256_ps128(
x));
31752 iWindow += windowWidth8 * 8;
31756 #if defined(MA_SUPPORT_SSE2)
31757 if (pSRC->useSSE2) {
31758 __m128 t = _mm_set1_ps((timeIn - iTimeInF));
31759 __m128
r = _mm_set1_ps(0);
31761 ma_int32 windowWidth4 = windowWidthSIMD2 >> 2;
31763 for (iWindow4 = 0; iWindow4 < windowWidth4; iWindow4 += 1) {
31764 __m128* s = (__m128*)windowSamples + iWindow4;
31765 __m128*
w = (__m128*)iWindowF + iWindow4;
31767 __m128
a = ma_src_sinc__interpolation_factor__sse2(pSRC, _mm_sub_ps(t, *
w));
31768 r = _mm_add_ps(
r, _mm_mul_ps(*s,
a));
31771 sampleOut += ((
float*)(&
r))[0];
31772 sampleOut += ((
float*)(&
r))[1];
31773 sampleOut += ((
float*)(&
r))[2];
31774 sampleOut += ((
float*)(&
r))[3];
31776 iWindow += windowWidth4 * 4;
31780 #if defined(MA_SUPPORT_NEON)
31781 if (pSRC->useNEON) {
31782 float32x4_t t = vmovq_n_f32((timeIn - iTimeInF));
31783 float32x4_t
r = vmovq_n_f32(0);
31785 ma_int32 windowWidth4 = windowWidthSIMD2 >> 2;
31787 for (iWindow4 = 0; iWindow4 < windowWidth4; iWindow4 += 1) {
31788 float32x4_t* s = (float32x4_t*)windowSamples + iWindow4;
31789 float32x4_t*
w = (float32x4_t*)iWindowF + iWindow4;
31791 float32x4_t
a = ma_src_sinc__interpolation_factor__neon(pSRC, vsubq_f32(t, *
w));
31792 r = vaddq_f32(
r, vmulq_f32(*s,
a));
31795 sampleOut += ((
float*)(&
r))[0];
31796 sampleOut += ((
float*)(&
r))[1];
31797 sampleOut += ((
float*)(&
r))[2];
31798 sampleOut += ((
float*)(&
r))[3];
31800 iWindow += windowWidth4 * 4;
31809 tScalar = (timeIn - iTimeIn);
31810 for (; iWindow < windowWidth2; iWindow += 1) {
31811 float s = windowSamples[iWindow];
31812 float w = iWindowF[iWindow];
31814 float a = ma_src_sinc__interpolation_factor(pSRC, (tScalar -
w));
31820 ppNextSamplesOut[iChannel][iSample] = (float)sampleOut;
31825 ppNextSamplesOut[iChannel] += outputFramesToRead;
31828 totalOutputFramesRead += outputFramesToRead;
31830 prevWindowPosInSamples = pSRC->sinc.windowPosInSamples;
31832 pSRC->sinc.timeIn += ((
ma_int64)outputFramesToRead * factor);
31833 pSRC->sinc.windowPosInSamples = (
ma_uint32)pSRC->sinc.timeIn;
31834 pSRC->sinc.inputFrameCount -= pSRC->sinc.windowPosInSamples - prevWindowPosInSamples;
31837 availableOutputFrames = (
ma_uint32)((timeInEnd - pSRC->sinc.timeIn) * inverseFactor);
31839 if (availableOutputFrames == 0) {
31840 size_t samplesToMove = ma_countof(pSRC->sinc.input[0]) - pSRC->sinc.windowPosInSamples;
31842 pSRC->sinc.timeIn -= ma_floorf(pSRC->sinc.timeIn);
31843 pSRC->sinc.windowPosInSamples = 0;
31846 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
31847 memmove(pSRC->sinc.input[iChannel], pSRC->sinc.input[iChannel] + ma_countof(pSRC->sinc.input[iChannel]) - samplesToMove, samplesToMove *
sizeof(*pSRC->sinc.input[iChannel]));
31852 if (pSRC->isEndOfInputLoaded) {
31853 pSRC->isEndOfInputLoaded =
MA_FALSE;
31861 ma_assert(pSRC->isEndOfInputLoaded ==
MA_FALSE);
31863 if (pSRC->sinc.inputFrameCount <= pSRC->config.sinc.windowWidth || availableOutputFrames == 0) {
31869 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
31870 ppInputDst[iChannel] = pSRC->sinc.input[iChannel] + pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount;
31874 framesToReadFromClient = ma_countof(pSRC->sinc.input[0]) - (pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount);
31876 framesReadFromClient = 0;
31877 if (framesToReadFromClient > 0) {
31878 framesReadFromClient = pSRC->config.onReadDeinterleaved(pSRC, framesToReadFromClient, (
void**)ppInputDst, pUserData);
31881 if (framesReadFromClient != framesToReadFromClient) {
31882 pSRC->isEndOfInputLoaded =
MA_TRUE;
31884 pSRC->isEndOfInputLoaded =
MA_FALSE;
31887 if (framesReadFromClient != 0) {
31888 pSRC->sinc.inputFrameCount += framesReadFromClient;
31891 if (pSRC->config.neverConsumeEndOfInput) {
31892 if ((pSRC->sinc.inputFrameCount * inverseFactor) <= pSRC->config.sinc.windowWidth) {
31896 if ((pSRC->sinc.inputFrameCount * inverseFactor) < 1) {
31903 leftoverFrames = ma_countof(pSRC->sinc.input[0]) - (pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount);
31904 if (leftoverFrames > 0) {
31905 for (iChannel = 0; iChannel < pSRC->config.channels; iChannel += 1) {
31906 ma_zero_memory(pSRC->sinc.input[iChannel] + pSRC->config.sinc.windowWidth + pSRC->sinc.inputFrameCount, leftoverFrames *
sizeof(
float));
31912 return totalOutputFramesRead;
31924 if (formatOut == formatIn) {
31997 if (pInterleavedPCMFrames ==
NULL || ppDeinterleavedPCMFrames ==
NULL) {
32007 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
32009 for (iChannel = 0; iChannel < channels; ++iChannel) {
32011 pDstS16[iPCMFrame] = pSrcS16[iPCMFrame*channels+iChannel];
32018 const float* pSrcF32 = (
const float*)pInterleavedPCMFrames;
32020 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
32022 for (iChannel = 0; iChannel < channels; ++iChannel) {
32023 float* pDstF32 = (
float*)ppDeinterleavedPCMFrames[iChannel];
32024 pDstF32[iPCMFrame] = pSrcF32[iPCMFrame*channels+iChannel];
32033 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
32035 for (iChannel = 0; iChannel < channels; ++iChannel) {
32036 void* pDst = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
32037 const void* pSrc = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*channels+iChannel)*sampleSizeInBytes);
32038 memcpy(pDst, pSrc, sampleSizeInBytes);
32053 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
32055 for (iChannel = 0; iChannel < channels; ++iChannel) {
32056 const ma_int16* pSrcS16 = (
const ma_int16*)ppDeinterleavedPCMFrames[iChannel];
32057 pDstS16[iPCMFrame*channels+iChannel] = pSrcS16[iPCMFrame];
32064 float* pDstF32 = (
float*)pInterleavedPCMFrames;
32066 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
32068 for (iChannel = 0; iChannel < channels; ++iChannel) {
32069 const float* pSrcF32 = (
const float*)ppDeinterleavedPCMFrames[iChannel];
32070 pDstF32[iPCMFrame*channels+iChannel] = pSrcF32[iPCMFrame];
32079 for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
32081 for (iChannel = 0; iChannel < channels; ++iChannel) {
32082 void* pDst = ma_offset_ptr(pInterleavedPCMFrames, (iPCMFrame*channels+iChannel)*sampleSizeInBytes);
32083 const void* pSrc = ma_offset_ptr(ppDeinterleavedPCMFrames[iChannel], iPCMFrame*sampleSizeInBytes);
32084 memcpy(pDst, pSrc, sampleSizeInBytes);
32096 void* pUserDataForClient;
32097 } ma_pcm_converter_callback_data;
32101 ma_pcm_converter_callback_data* pData;
32106 pData = (ma_pcm_converter_callback_data*)pUserData;
32107 ma_assert(pData !=
NULL);
32109 pDSP = pData->pDSP;
32110 ma_assert(pDSP !=
NULL);
32112 return pDSP->onRead(pDSP, pFramesOut, frameCount, pData->pUserDataForClient);
32117 ma_pcm_converter_callback_data* pData;
32122 pData = (ma_pcm_converter_callback_data*)pUserData;
32123 ma_assert(pData !=
NULL);
32125 pDSP = pData->pDSP;
32126 ma_assert(pDSP !=
NULL);
32129 ma_assert(pDSP->isPreFormatConversionRequired ==
MA_FALSE);
32130 ma_assert(pDSP->isChannelRoutingRequired ==
MA_FALSE);
32131 ma_assert(pDSP->isSRCRequired ==
MA_FALSE);
32133 return pDSP->onRead(pDSP, pFramesOut, frameCount, pData->pUserDataForClient);
32138 ma_pcm_converter_callback_data* pData;
32143 pData = (ma_pcm_converter_callback_data*)pUserData;
32144 ma_assert(pData !=
NULL);
32146 pDSP = pData->pDSP;
32147 ma_assert(pDSP !=
NULL);
32149 if (!pDSP->isChannelRoutingAtStart) {
32152 if (pDSP->isSRCRequired) {
32160 ma_uint32 ma_pcm_converter__src_on_read_deinterleaved(
ma_src* pSRC,
ma_uint32 frameCount,
void** ppSamplesOut,
void* pUserData)
32162 ma_pcm_converter_callback_data* pData;
32167 pData = (ma_pcm_converter_callback_data*)pUserData;
32168 ma_assert(pData !=
NULL);
32170 pDSP = pData->pDSP;
32171 ma_assert(pDSP !=
NULL);
32174 if (pDSP->isChannelRoutingAtStart) {
32183 ma_pcm_converter_callback_data* pData;
32188 pData = (ma_pcm_converter_callback_data*)pUserData;
32189 ma_assert(pData !=
NULL);
32191 pDSP = pData->pDSP;
32192 ma_assert(pDSP !=
NULL);
32195 if (pDSP->isChannelRoutingAtStart) {
32198 if (pDSP->isSRCRequired) {
32210 if (pDSP ==
NULL) {
32214 ma_zero_object(pDSP);
32215 pDSP->onRead = pConfig->
onRead;
32275 pDSP->isSRCRequired =
MA_TRUE;
32278 pDSP->isChannelRoutingRequired =
MA_TRUE;
32282 if (!pDSP->isSRCRequired && !pDSP->isChannelRoutingRequired) {
32285 pDSP->isPostFormatConversionRequired =
MA_TRUE;
32288 pDSP->isPreFormatConversionRequired =
MA_TRUE;
32289 pDSP->isPostFormatConversionRequired =
MA_TRUE;
32293 if (!pDSP->isPreFormatConversionRequired && !pDSP->isPostFormatConversionRequired && !pDSP->isChannelRoutingRequired && !pDSP->isSRCRequired) {
32294 pDSP->isPassthrough =
MA_TRUE;
32299 pDSP->isChannelRoutingAtStart =
MA_TRUE;
32315 ma_pcm_converter__pre_format_converter_on_read,
32344 if (pDSP->isPreFormatConversionRequired) {
32345 postFormatConverterConfig.
onReadDeinterleaved = ma_pcm_converter__post_format_converter_on_read_deinterleaved;
32348 postFormatConverterConfig.
onRead = ma_pcm_converter__post_format_converter_on_read;
32363 ma_pcm_converter__src_on_read_deinterleaved,
32372 ma_copy_memory(&srcConfig.
sinc, &pConfig->
sinc,
sizeof(pConfig->
sinc));
32388 ma_pcm_converter__channel_router_on_read_deinterleaved,
32414 if (pDSP ==
NULL) {
32419 if (sampleRateIn == 0) {
32424 if (!pDSP->isDynamicSampleRateAllowed) {
32428 ma_atomic_exchange_32(&pDSP->src.config.sampleRateIn, sampleRateIn);
32429 return ma_pcm_converter_refresh_sample_rate(pDSP);
32434 if (pDSP ==
NULL) {
32439 if (sampleRateOut == 0) {
32444 if (!pDSP->isDynamicSampleRateAllowed) {
32448 ma_atomic_exchange_32(&pDSP->src.config.sampleRateOut, sampleRateOut);
32449 return ma_pcm_converter_refresh_sample_rate(pDSP);
32454 if (pDSP ==
NULL) {
32459 if (sampleRateIn == 0 || sampleRateOut == 0) {
32464 if (!pDSP->isDynamicSampleRateAllowed) {
32468 ma_atomic_exchange_32(&pDSP->src.config.sampleRateIn, sampleRateIn);
32469 ma_atomic_exchange_32(&pDSP->src.config.sampleRateOut, sampleRateOut);
32471 return ma_pcm_converter_refresh_sample_rate(pDSP);
32476 ma_pcm_converter_callback_data
data;
32478 if (pDSP ==
NULL || pFramesOut ==
NULL) {
32483 if (pDSP->isPassthrough) {
32484 if (frameCount <= 0xFFFFFFFF) {
32485 return (
ma_uint32)pDSP->onRead(pDSP, pFramesOut, (
ma_uint32)frameCount, pDSP->pUserData);
32490 while (totalFramesRead < frameCount) {
32492 ma_uint64 framesRemaining = (frameCount - totalFramesRead);
32493 ma_uint64 framesToReadRightNow = framesRemaining;
32494 if (framesToReadRightNow > 0xFFFFFFFF) {
32495 framesToReadRightNow = 0xFFFFFFFF;
32498 framesRead = pDSP->onRead(pDSP, pNextFramesOut, (
ma_uint32)framesToReadRightNow, pDSP->pUserData);
32499 if (framesRead == 0) {
32503 pNextFramesOut += framesRead * pDSP->channelRouter.config.channelsOut *
ma_get_bytes_per_sample(pDSP->formatConverterOut.config.formatOut);
32504 totalFramesRead += framesRead;
32507 return totalFramesRead;
32512 ma_assert(pDSP->isPostFormatConversionRequired ==
MA_TRUE);
32515 data.pUserDataForClient = pDSP->pUserData;
32522 const void* pDataIn;
32528 } ma_convert_frames__data;
32532 ma_convert_frames__data* pData;
32539 pData = (ma_convert_frames__data*)pUserData;
32540 ma_assert(pData !=
NULL);
32541 ma_assert(pData->totalFrameCount >= pData->iNextFrame);
32543 framesToRead = frameCount;
32544 framesRemaining = (pData->totalFrameCount - pData->iNextFrame);
32545 if (framesToRead > framesRemaining) {
32546 framesToRead = (
ma_uint32)framesRemaining;
32549 frameSizeInBytes = ma_get_bytes_per_frame(pData->formatIn, pData->channelsIn);
32551 if (!pData->isFeedingZeros) {
32552 ma_copy_memory(pFramesOut, (
const ma_uint8*)pData->pDataIn + (frameSizeInBytes * pData->iNextFrame), frameSizeInBytes * framesToRead);
32554 ma_zero_memory(pFramesOut, frameSizeInBytes * framesToRead);
32557 pData->iNextFrame += framesToRead;
32558 return framesToRead;
32564 ma_zero_object(&
config);
32577 ma_zero_object(&
config);
32578 config.formatIn = formatIn;
32579 config.channelsIn = channelsIn;
32580 config.sampleRateIn = sampleRateIn;
32581 config.formatOut = formatOut;
32582 config.channelsOut = channelsOut;
32583 config.sampleRateOut = sampleRateOut;
32584 if (channelMapIn !=
NULL) {
32585 ma_copy_memory(
config.channelMapIn, channelMapIn,
sizeof(
config.channelMapIn));
32587 if (channelMapOut !=
NULL) {
32588 ma_copy_memory(
config.channelMapOut, channelMapOut,
sizeof(
config.channelMapOut));
32591 config.pUserData = pUserData;
32606 return ma_convert_frames_ex(pOut, formatOut, channelsOut, sampleRateOut, channelMapOut, pIn, formatIn, channelsIn, sampleRateIn, channelMapIn, frameCount);
32609 ma_uint64 ma_convert_frames_ex(
void* pOut,
ma_format formatOut,
ma_uint32 channelsOut,
ma_uint32 sampleRateOut,
ma_channel channelMapOut[
MA_MAX_CHANNELS],
const void* pIn,
ma_format formatIn,
ma_uint32 channelsIn,
ma_uint32 sampleRateIn,
ma_channel channelMapIn[
MA_MAX_CHANNELS],
ma_uint64 frameCount)
32612 ma_convert_frames__data
data;
32617 if (frameCount == 0) {
32621 frameCountOut = ma_calculate_frame_count_after_src(sampleRateOut, sampleRateIn, frameCount);
32622 if (pOut ==
NULL) {
32623 return frameCountOut;
32626 data.pDataIn = pIn;
32627 data.formatIn = formatIn;
32628 data.channelsIn = channelsIn;
32629 data.totalFrameCount = frameCount;
32630 data.iNextFrame = 0;
32633 ma_zero_object(&converterConfig);
32635 converterConfig.
formatIn = formatIn;
32638 if (channelMapIn !=
NULL) {
32647 if (channelMapOut !=
NULL) {
32653 converterConfig.
onRead = ma_convert_frames__on_read;
32666 if (totalFramesRead < frameCountOut) {
32667 ma_uint32 bpfOut = ma_get_bytes_per_frame(formatOut, channelsOut);
32670 data.totalFrameCount = ((
ma_uint64)0xFFFFFFFF << 32) | 0xFFFFFFFF;
32673 while (totalFramesRead < frameCountOut) {
32677 framesToRead = (frameCountOut - totalFramesRead);
32678 ma_assert(framesToRead > 0);
32680 framesJustRead =
ma_pcm_converter_read(&converter, ma_offset_ptr(pOut, totalFramesRead * bpfOut), framesToRead);
32681 totalFramesRead += framesJustRead;
32683 if (framesJustRead < framesToRead) {
32689 if (totalFramesRead < frameCountOut) {
32690 ma_zero_memory_64(ma_offset_ptr(pOut, totalFramesRead * bpfOut), ((frameCountOut - totalFramesRead) * bpfOut));
32691 totalFramesRead = frameCountOut;
32695 ma_assert(totalFramesRead == frameCountOut);
32696 return totalFramesRead;
32707 return encodedOffset & 0x7FFFFFFF;
32712 return encodedOffset & 0x80000000;
32717 ma_assert(pRB !=
NULL);
32723 ma_assert(pRB !=
NULL);
32729 return offsetLoopFlag | offsetInBytes;
32734 ma_assert(pOffsetInBytes !=
NULL);
32735 ma_assert(pOffsetLoopFlag !=
NULL);
32737 *pOffsetInBytes = ma_rb__extract_offset_in_bytes(encodedOffset);
32738 *pOffsetLoopFlag = ma_rb__extract_offset_loop_flag(encodedOffset);
32742 ma_result ma_rb_init_ex(
size_t subbufferSizeInBytes,
size_t subbufferCount,
size_t subbufferStrideInBytes,
void* pOptionalPreallocatedBuffer,
ma_rb* pRB)
32750 if (subbufferSizeInBytes == 0 || subbufferCount == 0) {
32754 if (subbufferSizeInBytes > maxSubBufferSize) {
32759 ma_zero_object(pRB);
32763 if (pOptionalPreallocatedBuffer !=
NULL) {
32765 pRB->
pBuffer = pOptionalPreallocatedBuffer;
32767 size_t bufferSizeInBytes;
32781 ma_zero_memory(pRB->
pBuffer, bufferSizeInBytes);
32790 return ma_rb_init_ex(bufferSizeInBytes, 1, 0, pOptionalPreallocatedBuffer, pRB);
32822 size_t bytesAvailable;
32823 size_t bytesRequested;
32825 if (pRB ==
NULL || pSizeInBytes ==
NULL || ppBufferOut ==
NULL) {
32831 ma_rb__deconstruct_offset(
writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
32834 ma_rb__deconstruct_offset(
readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
32840 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
32841 bytesAvailable = writeOffsetInBytes - readOffsetInBytes;
32846 bytesRequested = *pSizeInBytes;
32847 if (bytesRequested > bytesAvailable) {
32848 bytesRequested = bytesAvailable;
32851 *pSizeInBytes = bytesRequested;
32852 (*ppBufferOut) = ma_rb__get_read_ptr(pRB);
32870 if (pBufferOut != ma_rb__get_read_ptr(pRB)) {
32875 ma_rb__deconstruct_offset(
readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
32878 newReadOffsetInBytes = (
ma_uint32)(readOffsetInBytes + sizeInBytes);
32884 newReadOffsetLoopFlag = readOffsetLoopFlag;
32886 newReadOffsetInBytes = 0;
32887 newReadOffsetLoopFlag ^= 0x80000000;
32890 ma_atomic_exchange_32(&pRB->
encodedReadOffset, ma_rb__construct_offset(newReadOffsetLoopFlag, newReadOffsetInBytes));
32902 size_t bytesAvailable;
32903 size_t bytesRequested;
32905 if (pRB ==
NULL || pSizeInBytes ==
NULL || ppBufferOut ==
NULL) {
32911 ma_rb__deconstruct_offset(
readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
32914 ma_rb__deconstruct_offset(
writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
32921 if (writeOffsetLoopFlag == readOffsetLoopFlag) {
32924 bytesAvailable = readOffsetInBytes - writeOffsetInBytes;
32927 bytesRequested = *pSizeInBytes;
32928 if (bytesRequested > bytesAvailable) {
32929 bytesRequested = bytesAvailable;
32932 *pSizeInBytes = bytesRequested;
32933 *ppBufferOut = ma_rb__get_write_ptr(pRB);
32937 ma_zero_memory(*ppBufferOut, *pSizeInBytes);
32956 if (pBufferOut != ma_rb__get_write_ptr(pRB)) {
32961 ma_rb__deconstruct_offset(
writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
32964 newWriteOffsetInBytes = (
ma_uint32)(writeOffsetInBytes + sizeInBytes);
32970 newWriteOffsetLoopFlag = writeOffsetLoopFlag;
32972 newWriteOffsetInBytes = 0;
32973 newWriteOffsetLoopFlag ^= 0x80000000;
32976 ma_atomic_exchange_32(&pRB->
encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetLoopFlag, newWriteOffsetInBytes));
32996 ma_rb__deconstruct_offset(
readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
32999 ma_rb__deconstruct_offset(
writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
33001 newReadOffsetInBytes = readOffsetInBytes;
33002 newReadOffsetLoopFlag = readOffsetLoopFlag;
33005 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
33006 if ((readOffsetInBytes + offsetInBytes) > writeOffsetInBytes) {
33007 newReadOffsetInBytes = writeOffsetInBytes;
33009 newReadOffsetInBytes = (
ma_uint32)(readOffsetInBytes + offsetInBytes);
33015 newReadOffsetLoopFlag ^= 0x80000000;
33017 newReadOffsetInBytes = (
ma_uint32)(readOffsetInBytes + offsetInBytes);
33021 ma_atomic_exchange_32(&pRB->
encodedReadOffset, ma_rb__construct_offset(newReadOffsetInBytes, newReadOffsetLoopFlag));
33041 ma_rb__deconstruct_offset(
readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
33044 ma_rb__deconstruct_offset(
writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
33046 newWriteOffsetInBytes = writeOffsetInBytes;
33047 newWriteOffsetLoopFlag = writeOffsetLoopFlag;
33050 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
33054 newWriteOffsetLoopFlag ^= 0x80000000;
33056 newWriteOffsetInBytes = (
ma_uint32)(writeOffsetInBytes + offsetInBytes);
33059 if ((writeOffsetInBytes + offsetInBytes) > readOffsetInBytes) {
33060 newWriteOffsetInBytes = readOffsetInBytes;
33062 newWriteOffsetInBytes = (
ma_uint32)(writeOffsetInBytes + offsetInBytes);
33066 ma_atomic_exchange_32(&pRB->
encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetInBytes, newWriteOffsetLoopFlag));
33084 ma_rb__deconstruct_offset(
readOffset, &readOffsetInBytes, &readOffsetLoopFlag);
33087 ma_rb__deconstruct_offset(
writeOffset, &writeOffsetInBytes, &writeOffsetLoopFlag);
33089 if (readOffsetLoopFlag == writeOffsetLoopFlag) {
33090 return writeOffsetInBytes - readOffsetInBytes;
33164 ma_assert(pRB !=
NULL);
33178 ma_zero_object(pRB);
33180 bpf = ma_get_bytes_per_frame(
format, channels);
33185 result =
ma_rb_init_ex(subbufferSizeInFrames*bpf, subbufferCount, subbufferStrideInFrames*bpf, pOptionalPreallocatedBuffer, &pRB->
rb);
33221 size_t sizeInBytes;
33224 if (pRB ==
NULL || pSizeInFrames ==
NULL) {
33228 sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
33235 *pSizeInFrames = (
ma_uint32)(sizeInBytes / (
size_t)ma_pcm_rb_get_bpf(pRB));
33250 size_t sizeInBytes;
33257 sizeInBytes = *pSizeInFrames * ma_pcm_rb_get_bpf(pRB);
33264 *pSizeInFrames = (
ma_uint32)(sizeInBytes / ma_pcm_rb_get_bpf(pRB));
33367 return MA_MALLOC(sz);
33372 return MA_REALLOC(p, sz);
33386 if (alignment == 0) {
33390 extraBytes = alignment-1 +
sizeof(
void*);
33392 pUnaligned =
ma_malloc(sz + extraBytes);
33393 if (pUnaligned ==
NULL) {
33398 ((
void**)pAligned)[-1] = pUnaligned;
33415 case ma_format_s24:
return "24-bit Signed Integer (Tightly Packed)";
33418 default:
return "Invalid";
33425 for (i = 0; i < channels; ++i) {
33426 pOut[i] = ma_mix_f32(pInA[i], pInB[i], factor);
33450 #ifndef MA_NO_DECODING
33452 size_t ma_decoder_read_bytes(
ma_decoder* pDecoder,
void* pBufferOut,
size_t bytesToRead)
33456 ma_assert(pDecoder !=
NULL);
33457 ma_assert(pBufferOut !=
NULL);
33459 bytesRead = pDecoder->
onRead(pDecoder, pBufferOut, bytesToRead);
33469 ma_assert(pDecoder !=
NULL);
33471 wasSuccessful = pDecoder->
onSeek(pDecoder, byteOffset, origin);
33472 if (wasSuccessful) {
33480 return wasSuccessful;
33485 ma_assert(pDecoder !=
NULL);
33488 ma_uint64 bytesToSeekThisIteration = 0x7FFFFFFF;
33489 if (bytesToSeekThisIteration > byteOffset) {
33490 bytesToSeekThisIteration = byteOffset;
33497 byteOffset -= bytesToSeekThisIteration;
33501 while (byteOffset > 0) {
33502 ma_uint64 bytesToSeekThisIteration = 0x7FFFFFFF;
33503 if (bytesToSeekThisIteration > byteOffset) {
33504 bytesToSeekThisIteration = byteOffset;
33511 byteOffset -= bytesToSeekThisIteration;
33521 ma_zero_object(&
config);
33522 config.format = outputFormat;
33523 config.channels = outputChannels;
33524 config.sampleRate = outputSampleRate;
33533 if (pConfig !=
NULL) {
33536 ma_zero_object(&
config);
33546 ma_assert(pDecoder !=
NULL);
33591 size_t ma_decoder_internal_on_read__wav(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
33594 ma_assert(pDecoder !=
NULL);
33596 return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead);
33602 ma_assert(pDecoder !=
NULL);
33615 ma_assert(pDecoder !=
NULL);
33618 ma_assert(pWav !=
NULL);
33638 ma_assert(pWav !=
NULL);
33665 ma_assert(pConfig !=
NULL);
33666 ma_assert(pDecoder !=
NULL);
33669 if (pWav ==
NULL) {
33674 if (!
drwav_init(pWav, ma_decoder_internal_on_read__wav, ma_decoder_internal_on_seek__wav, pDecoder,
NULL)) {
33680 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__wav;
33681 pDecoder->
onUninit = ma_decoder_internal_on_uninit__wav;
33723 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__wav);
33736 #define MA_HAS_FLAC
33738 size_t ma_decoder_internal_on_read__flac(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
33741 ma_assert(pDecoder !=
NULL);
33743 return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead);
33749 ma_assert(pDecoder !=
NULL);
33762 ma_assert(pDecoder !=
NULL);
33765 ma_assert(pFlac !=
NULL);
33785 ma_assert(pFlac !=
NULL);
33811 ma_assert(pConfig !=
NULL);
33812 ma_assert(pDecoder !=
NULL);
33815 pFlac =
drflac_open(ma_decoder_internal_on_read__flac, ma_decoder_internal_on_seek__flac, pDecoder,
NULL);
33816 if (pFlac ==
NULL) {
33821 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__flac;
33822 pDecoder->
onUninit = ma_decoder_internal_on_uninit__flac;
33841 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__flac);
33852 #ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
33853 #define MA_HAS_VORBIS
33856 #define MA_VORBIS_DATA_CHUNK_SIZE 4096
33863 size_t dataCapacity;
33866 float** ppPacketData;
33867 } ma_vorbis_decoder;
33871 float* pFramesOutF;
33874 ma_assert(pVorbis !=
NULL);
33875 ma_assert(pDecoder !=
NULL);
33877 pFramesOutF = (
float*)pFramesOut;
33879 totalFramesRead = 0;
33880 while (frameCount > 0) {
33882 while (pVorbis->framesRemaining > 0 && frameCount > 0) {
33885 pFramesOutF[0] = pVorbis->ppPacketData[iChannel][pVorbis->framesConsumed];
33889 pVorbis->framesConsumed += 1;
33890 pVorbis->framesRemaining -= 1;
33892 totalFramesRead += 1;
33895 if (frameCount == 0) {
33899 ma_assert(pVorbis->framesRemaining == 0);
33905 int consumedDataSize;
33907 if (pVorbis->dataSize > INT_MAX) {
33913 if (consumedDataSize != 0) {
33914 size_t leftoverDataSize = (pVorbis->dataSize - (size_t)consumedDataSize);
33916 for (i = 0; i < leftoverDataSize; ++i) {
33917 pVorbis->pData[i] = pVorbis->pData[i + consumedDataSize];
33920 pVorbis->dataSize = leftoverDataSize;
33921 pVorbis->framesConsumed = 0;
33922 pVorbis->framesRemaining = samplesRead;
33927 if (pVorbis->dataCapacity == pVorbis->dataSize) {
33929 size_t newCap = pVorbis->dataCapacity + MA_VORBIS_DATA_CHUNK_SIZE;
33933 if (pNewData ==
NULL) {
33934 return totalFramesRead;
33937 pVorbis->pData = pNewData;
33938 pVorbis->dataCapacity = newCap;
33942 bytesRead = ma_decoder_read_bytes(pDecoder, pVorbis->pData + pVorbis->dataSize, (pVorbis->dataCapacity - pVorbis->dataSize));
33943 if (bytesRead == 0) {
33944 return totalFramesRead;
33947 pVorbis->dataSize += bytesRead;
33952 return totalFramesRead;
33959 ma_assert(pVorbis !=
NULL);
33960 ma_assert(pDecoder !=
NULL);
33972 pVorbis->framesConsumed = 0;
33973 pVorbis->framesRemaining = 0;
33974 pVorbis->dataSize = 0;
33976 while (frameIndex > 0) {
33979 if (framesToRead > frameIndex) {
33983 framesRead = ma_vorbis_decoder_read_pcm_frames(pVorbis, pDecoder,
buffer, framesToRead);
33984 if (framesRead == 0) {
33988 frameIndex -= framesRead;
33997 ma_vorbis_decoder* pVorbis = (ma_vorbis_decoder*)pDecoder->
pInternalDecoder;
33998 ma_assert(pVorbis !=
NULL);
34000 return ma_vorbis_decoder_seek_to_pcm_frame(pVorbis, pDecoder, frameIndex);
34005 ma_vorbis_decoder* pVorbis = (ma_vorbis_decoder*)pDecoder->
pInternalDecoder;
34006 ma_assert(pVorbis !=
NULL);
34018 ma_vorbis_decoder* pVorbis;
34023 ma_assert(pDecoder !=
NULL);
34027 ma_assert(pVorbis !=
NULL);
34029 return ma_vorbis_decoder_read_pcm_frames(pVorbis, pDecoder, pFramesOut, frameCount);
34044 size_t dataCapacity = 0;
34047 size_t vorbisDataSize;
34048 ma_vorbis_decoder* pVorbis;
34050 ma_assert(pConfig !=
NULL);
34051 ma_assert(pDecoder !=
NULL);
34059 int vorbisError = 0;
34060 int consumedDataSize = 0;
34062 dataCapacity += MA_VORBIS_DATA_CHUNK_SIZE;
34064 if (pNewData ==
NULL) {
34072 bytesRead = ma_decoder_read_bytes(pDecoder, pData +
dataSize, (dataCapacity -
dataSize));
34073 if (bytesRead == 0) {
34083 if (pInternalVorbis !=
NULL) {
34088 size_t leftoverDataSize = (
dataSize - (size_t)consumedDataSize);
34090 for (i = 0; i < leftoverDataSize; ++i) {
34091 pData[i] = pData[i + consumedDataSize];
34116 vorbisDataSize =
sizeof(ma_vorbis_decoder) +
sizeof(
float)*vorbisInfo.
max_frame_size;
34117 pVorbis = (ma_vorbis_decoder*)
ma_malloc(vorbisDataSize);
34118 if (pVorbis ==
NULL) {
34124 ma_zero_memory(pVorbis, vorbisDataSize);
34125 pVorbis->pInternalVorbis = pInternalVorbis;
34126 pVorbis->pData = pData;
34128 pVorbis->dataCapacity = dataCapacity;
34130 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__vorbis;
34131 pDecoder->
onUninit = ma_decoder_internal_on_uninit__vorbis;
34141 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__vorbis);
34157 size_t ma_decoder_internal_on_read__mp3(
void* pUserData,
void* pBufferOut,
size_t bytesToRead)
34160 ma_assert(pDecoder !=
NULL);
34162 return ma_decoder_read_bytes(pDecoder, pBufferOut, bytesToRead);
34168 ma_assert(pDecoder !=
NULL);
34181 ma_assert(pDecoder !=
NULL);
34185 ma_assert(pMP3 !=
NULL);
34196 ma_assert(pMP3 !=
NULL);
34224 ma_assert(pConfig !=
NULL);
34225 ma_assert(pDecoder !=
NULL);
34228 if (pMP3 ==
NULL) {
34243 ma_zero_object(&mp3Config);
34246 if (!
drmp3_init(pMP3, ma_decoder_internal_on_read__mp3, ma_decoder_internal_on_seek__mp3, pDecoder, &mp3Config,
NULL)) {
34252 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__mp3;
34253 pDecoder->
onUninit = ma_decoder_internal_on_uninit__mp3;
34263 result = ma_decoder__init_dsp(pDecoder, pConfig, ma_decoder_internal_on_read_pcm_frames__mp3);
34283 ma_assert(pDecoder !=
NULL);
34287 return (
ma_uint32)ma_decoder_read_bytes(pDecoder, pFramesOut, frameCount * bpf) / bpf;
34295 ma_assert(pDecoder !=
NULL);
34303 if (totalBytesToSeek < 0x7FFFFFFF) {
34310 totalBytesToSeek -= 0x7FFFFFFF;
34312 while (totalBytesToSeek > 0) {
34313 ma_uint64 bytesToSeekThisIteration = totalBytesToSeek;
34314 if (bytesToSeekThisIteration > 0x7FFFFFFF) {
34315 bytesToSeekThisIteration = 0x7FFFFFFF;
34323 totalBytesToSeek -= bytesToSeekThisIteration;
34351 ma_assert(pConfigIn !=
NULL);
34352 ma_assert(pConfigOut !=
NULL);
34353 ma_assert(pDecoder !=
NULL);
34355 pDecoder->
onSeekToPCMFrame = ma_decoder_internal_on_seek_to_pcm_frame__raw;
34356 pDecoder->
onUninit = ma_decoder_internal_on_uninit__raw;
34365 result = ma_decoder__init_dsp(pDecoder, pConfigOut, ma_decoder_internal_on_read_pcm_frames__raw);
34375 ma_assert(pConfig !=
NULL);
34377 if (pDecoder ==
NULL) {
34381 ma_zero_object(pDecoder);
34383 if (onRead ==
NULL || onSeek ==
NULL) {
34387 pDecoder->
onRead = onRead;
34388 pDecoder->
onSeek = onSeek;
34400 config = ma_decoder_config_init_copy(pConfig);
34402 result = ma_decoder__preinit(onRead, onSeek, pUserData, &
config, pDecoder);
34408 return ma_decoder_init_wav__internal(&
config, pDecoder);
34419 config = ma_decoder_config_init_copy(pConfig);
34421 result = ma_decoder__preinit(onRead, onSeek, pUserData, &
config, pDecoder);
34427 return ma_decoder_init_flac__internal(&
config, pDecoder);
34438 config = ma_decoder_config_init_copy(pConfig);
34440 result = ma_decoder__preinit(onRead, onSeek, pUserData, &
config, pDecoder);
34445 #ifdef MA_HAS_VORBIS
34446 return ma_decoder_init_vorbis__internal(&
config, pDecoder);
34457 config = ma_decoder_config_init_copy(pConfig);
34459 result = ma_decoder__preinit(onRead, onSeek, pUserData, &
config, pDecoder);
34465 return ma_decoder_init_mp3__internal(&
config, pDecoder);
34476 config = ma_decoder_config_init_copy(pConfigOut);
34478 result = ma_decoder__preinit(onRead, onSeek, pUserData, &
config, pDecoder);
34483 return ma_decoder_init_raw__internal(pConfigIn, &
config, pDecoder);
34490 ma_assert(pConfig !=
NULL);
34491 ma_assert(pDecoder !=
NULL);
34504 result = ma_decoder_init_wav__internal(pConfig, pDecoder);
34512 result = ma_decoder_init_flac__internal(pConfig, pDecoder);
34518 #ifdef MA_HAS_VORBIS
34520 result = ma_decoder_init_vorbis__internal(pConfig, pDecoder);
34528 result = ma_decoder_init_mp3__internal(pConfig, pDecoder);
34547 config = ma_decoder_config_init_copy(pConfig);
34549 result = ma_decoder__preinit(onRead, onSeek, pUserData, &
config, pDecoder);
34554 return ma_decoder_init__internal(onRead, onSeek, pUserData, &
config, pDecoder);
34558 size_t ma_decoder__on_read_memory(
ma_decoder* pDecoder,
void* pBufferOut,
size_t bytesToRead)
34560 size_t bytesRemaining;
34565 if (bytesToRead > bytesRemaining) {
34566 bytesToRead = bytesRemaining;
34569 if (bytesToRead > 0) {
34574 return bytesToRead;
34580 if (byteOffset > 0) {
34605 ma_result result = ma_decoder__preinit(ma_decoder__on_read_memory, ma_decoder__on_seek_memory,
NULL, pConfig, pDecoder);
34627 config = ma_decoder_config_init_copy(pConfig);
34634 return ma_decoder_init__internal(ma_decoder__on_read_memory, ma_decoder__on_seek_memory,
NULL, &
config, pDecoder);
34642 config = ma_decoder_config_init_copy(pConfig);
34650 return ma_decoder_init_wav__internal(&
config, pDecoder);
34661 config = ma_decoder_config_init_copy(pConfig);
34669 return ma_decoder_init_flac__internal(&
config, pDecoder);
34680 config = ma_decoder_config_init_copy(pConfig);
34687 #ifdef MA_HAS_VORBIS
34688 return ma_decoder_init_vorbis__internal(&
config, pDecoder);
34699 config = ma_decoder_config_init_copy(pConfig);
34707 return ma_decoder_init_mp3__internal(&
config, pDecoder);
34718 config = ma_decoder_config_init_copy(pConfigOut);
34725 return ma_decoder_init_raw__internal(pConfigIn, &
config, pDecoder);
34728 #ifndef MA_NO_STDIO
34730 #if !defined(_MSC_VER) && !defined(__DMC__)
34731 #include <strings.h>
34735 const char* ma_path_file_name(
const char* path)
34737 const char* fileName;
34739 if (path ==
NULL) {
34746 while (path[0] !=
'\0') {
34747 if (path[0] ==
'/' || path[0] ==
'\\') {
34755 while (fileName[0] !=
'\0' && (fileName[0] ==
'/' || fileName[0] ==
'\\')) {
34762 const wchar_t* ma_path_file_name_w(
const wchar_t* path)
34764 const wchar_t* fileName;
34766 if (path ==
NULL) {
34773 while (path[0] !=
'\0') {
34774 if (path[0] ==
'/' || path[0] ==
'\\') {
34782 while (fileName[0] !=
'\0' && (fileName[0] ==
'/' || fileName[0] ==
'\\')) {
34790 const char* ma_path_extension(
const char* path)
34792 const char* extension;
34793 const char* lastOccurance;
34795 if (path ==
NULL) {
34799 extension = ma_path_file_name(path);
34800 lastOccurance =
NULL;
34803 while (extension[0] !=
'\0') {
34804 if (extension[0] ==
'.') {
34806 lastOccurance = extension;
34812 return (lastOccurance !=
NULL) ? lastOccurance : extension;
34815 const wchar_t* ma_path_extension_w(
const wchar_t* path)
34817 const wchar_t* extension;
34818 const wchar_t* lastOccurance;
34820 if (path ==
NULL) {
34824 extension = ma_path_file_name_w(path);
34825 lastOccurance =
NULL;
34828 while (extension[0] !=
'\0') {
34829 if (extension[0] ==
'.') {
34831 lastOccurance = extension;
34837 return (lastOccurance !=
NULL) ? lastOccurance : extension;
34841 ma_bool32 ma_path_extension_equal(
const char* path,
const char* extension)
34846 if (path ==
NULL || extension ==
NULL) {
34851 ext2 = ma_path_extension(path);
34853 #if defined(_MSC_VER) || defined(__DMC__)
34854 return _stricmp(ext1, ext2) == 0;
34856 return strcasecmp(ext1, ext2) == 0;
34860 ma_bool32 ma_path_extension_equal_w(
const wchar_t* path,
const wchar_t* extension)
34862 const wchar_t* ext1;
34863 const wchar_t* ext2;
34865 if (path ==
NULL || extension ==
NULL) {
34870 ext2 = ma_path_extension_w(path);
34872 #if defined(_MSC_VER) || defined(__DMC__)
34873 return _wcsicmp(ext1, ext2) == 0;
34882 const wchar_t* pext1 = ext1;
34883 const wchar_t* pext2 = ext2;
34887 ma_zero_object(&mbs1);
34888 ma_zero_object(&mbs2);
34890 if (wcsrtombs(ext1MB, &pext1,
sizeof(ext1MB), &mbs1) == (
size_t)-1) {
34893 if (wcsrtombs(ext2MB, &pext2,
sizeof(ext2MB), &mbs2) == (
size_t)-1) {
34897 return strcasecmp(ext1MB, ext2MB) == 0;
34903 size_t ma_decoder__on_read_stdio(
ma_decoder* pDecoder,
void* pBufferOut,
size_t bytesToRead)
34905 return fread(pBufferOut, 1, bytesToRead, (FILE*)pDecoder->
pUserData);
34917 if (pDecoder ==
NULL) {
34921 ma_zero_object(pDecoder);
34923 if (pFilePath ==
NULL || pFilePath[0] ==
'\0') {
34927 #if defined(_MSC_VER) && _MSC_VER >= 1400
34928 if (fopen_s(&pFile, pFilePath,
"rb") != 0) {
34932 pFile = fopen(pFilePath,
"rb");
34933 if (pFile ==
NULL) {
34949 if (pDecoder ==
NULL) {
34953 ma_zero_object(pDecoder);
34955 if (pFilePath ==
NULL || pFilePath[0] ==
'\0') {
34959 #if defined(_WIN32)
34961 #if defined(_MSC_VER) && _MSC_VER >= 1400
34962 if (_wfopen_s(&pFile, pFilePath, L
"rb") != 0) {
34966 pFile = _wfopen(pFilePath, L
"rb");
34967 if (pFile ==
NULL) {
34980 const wchar_t* pFilePathTemp = pFilePath;
34981 char* pFilePathMB =
NULL;
34984 ma_zero_object(&mbs);
34985 lenMB = wcsrtombs(
NULL, &pFilePathTemp, 0, &mbs);
34986 if (lenMB == (
size_t)-1) {
34990 pFilePathMB = (
char*)MA_MALLOC(lenMB + 1);
34991 if (pFilePathMB ==
NULL) {
34995 pFilePathTemp = pFilePath;
34996 ma_zero_object(&mbs);
34997 wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
34999 pFile = fopen(pFilePathMB,
"rb");
35001 MA_FREE(pFilePathMB);
35004 if (pFile ==
NULL) {
35018 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
35024 if (ma_path_extension_equal(pFilePath,
"wav")) {
35034 if (ma_path_extension_equal(pFilePath,
"flac")) {
35044 if (ma_path_extension_equal(pFilePath,
"mp3")) {
35054 return ma_decoder_init(ma_decoder__on_read_stdio, ma_decoder__on_seek_stdio, pDecoder->
pUserData, pConfig, pDecoder);
35059 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
35069 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
35079 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
35089 ma_result result = ma_decoder__preinit_file(pFilePath, pConfig, pDecoder);
35100 ma_result result = ma_decoder__preinit_file_w(pFilePath, pConfig, pDecoder);
35106 if (ma_path_extension_equal_w(pFilePath, L
"wav")) {
35116 if (ma_path_extension_equal_w(pFilePath, L
"flac")) {
35126 if (ma_path_extension_equal_w(pFilePath, L
"mp3")) {
35136 return ma_decoder_init(ma_decoder__on_read_stdio, ma_decoder__on_seek_stdio, pDecoder->
pUserData, pConfig, pDecoder);
35141 ma_result result = ma_decoder__preinit_file_w(pFilePath, pConfig, pDecoder);
35151 ma_result result = ma_decoder__preinit_file_w(pFilePath, pConfig, pDecoder);
35161 ma_result result = ma_decoder__preinit_file_w(pFilePath, pConfig, pDecoder);
35171 ma_result result = ma_decoder__preinit_file_w(pFilePath, pConfig, pDecoder);
35182 if (pDecoder ==
NULL) {
35190 #ifndef MA_NO_STDIO
35192 if (pDecoder->
onRead == ma_decoder__on_read_stdio) {
35202 if (pDecoder ==
NULL) {
35215 if (pDecoder ==
NULL) {
35224 if (pDecoder ==
NULL) {
35242 void* pPCMFramesOut;
35244 ma_assert(pDecoder !=
NULL);
35246 totalFrameCount = 0;
35250 dataCapInFrames = 0;
35251 pPCMFramesOut =
NULL;
35257 if (totalFrameCount == dataCapInFrames) {
35258 void* pNewPCMFramesOut;
35259 ma_uint64 newDataCapInFrames = dataCapInFrames*2;
35260 if (newDataCapInFrames == 0) {
35261 newDataCapInFrames = 4096;
35270 pNewPCMFramesOut = (
void*)
ma_realloc(pPCMFramesOut, (
size_t)(newDataCapInFrames * bpf));
35271 if (pNewPCMFramesOut ==
NULL) {
35276 dataCapInFrames = newDataCapInFrames;
35277 pPCMFramesOut = pNewPCMFramesOut;
35280 frameCountToTryReading = dataCapInFrames - totalFrameCount;
35281 ma_assert(frameCountToTryReading > 0);
35284 totalFrameCount += framesJustRead;
35286 if (framesJustRead < frameCountToTryReading) {
35292 if (pConfigOut !=
NULL) {
35299 if (ppPCMFramesOut !=
NULL) {
35300 *ppPCMFramesOut = pPCMFramesOut;
35305 if (pFrameCountOut !=
NULL) {
35306 *pFrameCountOut = totalFrameCount;
35313 #ifndef MA_NO_STDIO
35320 if (pFrameCountOut !=
NULL) {
35321 *pFrameCountOut = 0;
35323 if (ppPCMFramesOut !=
NULL) {
35324 *ppPCMFramesOut =
NULL;
35327 if (pFilePath ==
NULL) {
35331 config = ma_decoder_config_init_copy(pConfig);
35338 return ma_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
35348 if (pFrameCountOut !=
NULL) {
35349 *pFrameCountOut = 0;
35351 if (ppPCMFramesOut !=
NULL) {
35352 *ppPCMFramesOut =
NULL;
35359 config = ma_decoder_config_init_copy(pConfig);
35366 return ma_decoder__full_decode_and_uninit(&decoder, pConfig, pFrameCountOut, ppPCMFramesOut);
35381 if (pSineWave ==
NULL) {
35384 ma_zero_object(pSineWave);
35386 if (amplitude == 0 || periodsPerSecond == 0) {
35390 if (amplitude > 1) {
35393 if (amplitude < -1) {
35399 pSineWave->
delta = MA_TAU_D / sampleRate;
35400 pSineWave->
time = 0;
35412 if (pSineWave ==
NULL) {
35416 if (ppFrames !=
NULL) {
35418 for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
35425 for (iChannel = 0; iChannel < channels; iChannel += 1) {
35426 ppFrames[0][iFrame*channels + iChannel] = s;
35429 for (iChannel = 0; iChannel < channels; iChannel += 1) {
35430 ppFrames[iChannel][iFrame] = s;
35441 #if defined(_MSC_VER)
35442 #pragma warning(pop)